Quellcode durchsuchen

移除界面侧滑功能及补充相关文档

修复 DialogManager 内存泄漏的问题
修复 Android 11 无法使用意图的问题
修复 Bugly 上报 Lottie 资源异常的问题
优化 SettingBar 自定义控件的代码逻辑
master
Android 轮子哥 vor 4 Jahren
Ursprung
Commit
48c6560163
25 geänderte Dateien mit 128 neuen und 136 gelöschten Zeilen
  1. BIN
      AndroidProject.apk
  2. 33
    21
      HelpDoc.md
  3. 0
    4
      app/build.gradle
  4. 35
    4
      app/src/main/AndroidManifest.xml
  5. 3
    2
      app/src/main/java/com/hjq/demo/action/StatusAction.java
  6. 0
    18
      app/src/main/java/com/hjq/demo/action/SwipeAction.java
  7. 1
    3
      app/src/main/java/com/hjq/demo/app/AppActivity.java
  8. 1
    11
      app/src/main/java/com/hjq/demo/app/AppApplication.java
  9. 3
    2
      app/src/main/java/com/hjq/demo/manager/DialogManager.java
  10. 2
    1
      app/src/main/java/com/hjq/demo/manager/InputTextManager.java
  11. 0
    1
      app/src/main/java/com/hjq/demo/ui/activity/CameraActivity.java
  12. 0
    5
      app/src/main/java/com/hjq/demo/ui/activity/CrashActivity.java
  13. 0
    5
      app/src/main/java/com/hjq/demo/ui/activity/GuideActivity.java
  14. 0
    5
      app/src/main/java/com/hjq/demo/ui/activity/HomeActivity.java
  15. 0
    5
      app/src/main/java/com/hjq/demo/ui/activity/ImagePreviewActivity.java
  16. 0
    5
      app/src/main/java/com/hjq/demo/ui/activity/LoginActivity.java
  17. 0
    5
      app/src/main/java/com/hjq/demo/ui/activity/RegisterActivity.java
  18. 0
    5
      app/src/main/java/com/hjq/demo/ui/activity/SplashActivity.java
  19. 1
    7
      app/src/main/java/com/hjq/demo/ui/activity/VideoPlayActivity.java
  20. 10
    3
      app/src/main/java/com/hjq/demo/ui/dialog/UpdateDialog.java
  21. 26
    18
      app/src/main/java/com/hjq/demo/widget/StatusLayout.java
  22. 4
    4
      app/src/main/res/values/strings.xml
  23. 2
    2
      build.gradle
  24. BIN
      picture/help/swipe.jpg
  25. 7
    0
      widget/src/main/java/com/hjq/widget/layout/SettingBar.java

BIN
AndroidProject.apk Datei anzeigen


+ 33
- 21
HelpDoc.md Datei anzeigen

@@ -4,23 +4,25 @@

* [为什么没有用 ButterKnife](#为什么没有用-butterknife)

* [为什么不用 ViewBinding](#为什么不用-viewbinding)
* [为什么没有用 ViewBinding](#为什么没有用-viewbinding)

* [为什么不用 DataBinding](#为什么不用-databinding)
* [为什么没有用 DataBinding](#为什么没有用-databinding)

* [为什么没有用组件化](#为什么没有用组件化)

* [为什么不用今日头条的适配方案](#为什么不用今日头条的适配方案)
* [为什么没有集成界面侧滑功能](#为什么没有集成界面侧滑功能)

* [为什么没有用今日头条的适配方案](#为什么没有用今日头条的适配方案)

* [字体大小为什么不用 dp 而用 sp](#字体大小为什么不用-dp-而用-sp)

* [为什么不用 DialogFragment 来防止内存泄漏](#为什么不用-dialogfragment-来防止内存泄漏)
* [为什么没有用 DialogFragment 来防止内存泄漏](#为什么没有用-dialogfragment-来防止内存泄漏)

* [为什么不用腾讯 X5 WebView](#为什么不用腾讯-x5-webview)
* [为什么没有用腾讯 X5 WebView](#为什么没有用腾讯-x5-webview)

* [为什么不用单 Activity 多 Fragment](#为什么不用单-activity-多-fragment)
* [为什么没有用单 Activity 多 Fragment](#为什么没有用单-activity-多-fragment)

* [为什么不用 ConstraintLayout 来写布局](#为什么不用-constraintlayout-来写布局)
* [为什么没有用 ConstraintLayout 来写布局](#为什么没有用-constraintlayout-来写布局)

* [为什么不拆成多个框架来做这件事](#为什么不拆成多个框架来做这件事)

@@ -30,7 +32,7 @@

* [为什么不加入 EventBus](#为什么不加入-eventbus)

* [为什么不用 Retrofit 和 RxJava](#为什么不用-retrofit-和-rxjava)
* [为什么没有用 Retrofit 和 RxJava](#为什么没有用-retrofit-和-rxjava)

* [为什么没有用 Jetpack 全家桶](#为什么没有用-jetpack-全家桶)

@@ -42,12 +44,14 @@

* [为什么没有关于列表多 type 的封装](#为什么没有关于列表多-type-的封装)

* [为什么不用 Dagger 框架](#为什么不用-dagger-框架)
* [为什么没有用 Dagger 框架](#为什么没有用-dagger-框架)

* [这不就是一个模板工程换成我也能写一个](#这不就是一个模板工程换成我也能写一个)

* [轮子哥你怎么看待层出不穷的新技术](#轮子哥你怎么看待层出不穷的新技术)

* [为什么没有集成界面侧滑功能](#为什么没有集成界面侧滑功能)

#### 为什么没有用 MVP

![](picture/help/mvp1.jpg)
@@ -75,7 +79,7 @@ Resource IDs will be non-final in Android Gradle Plugin version 5.0, avoid using

* 另外大家如果不想写 findViewById,我可以推荐一款自动生成 findViewById 的插件给大家:[FindViewByMe](https://plugins.jetbrains.com/plugin/8261-findviewbyme)

#### 为什么用 ViewBinding
#### 为什么没有用 ViewBinding

* 首先 ViewBinding 和 ButterKnife 有一个相同的毛病,就是自动生成一个类,然后在这个类里面进行 findViewById,但是有一个致命的缺点,每个 `Activity / Fragment / Dialog / Adapter` 都需要先初始化 ViewBinding 对象,因为每次生成的类名都是不固定的,所以无法在基类中封装处理,并且每次都要写 `binding.xxx` 才能操作控件。

@@ -92,7 +96,7 @@ binding.tv_data_name.setText("字符串");

* 另外大家如果不想写 findViewById,我可以推荐一款自动生成 findViewById 的插件给大家:[FindViewByMe](https://plugins.jetbrains.com/plugin/8261-findviewbyme)

#### 为什么用 DataBinding
#### 为什么没有用 DataBinding

* DataBinding 最大的优势在于,因为它可以在 xml 直接给 View 赋值,但它的优点正是它最致命的缺点,当业务逻辑简单时,会显得格外美好,但是一旦判断条件复杂起来,由于 xml 属性不能换行的特性,会导致无法在 xml 直接赋值又或者很长的一段代码堆在布局中,间接导致 CodeReview 时异常艰难,更别说在原有的基础上继续更新迭代,这对每一个开发者来讲无疑是一个巨大的灾难。

@@ -110,7 +114,15 @@ ActivityXxxxBinding binding = DataBindingUtil.setContentView(this, R.layout.acti

* AndroidProject 面对的是大众开发者,所以更倾向中小型的项目代码的设计,虽然我没有做过大型的项目,但是在我看来是差不多的,最大的不同可能是代码分类方式的不同,该做的事情不会少,该写的代码也不会少,就是业务和代码的体量上比我们大,所以他们要处理体量大所带来的的问题。

#### 为什么不用今日头条的适配方案
#### 为什么没有集成界面侧滑功能

* AndroidProject 其实有加入过这个功能,但是在 [v9.0 版本](https://github.com/getActivity/AndroidProject/releases/tag/9.0) 就移除了,原因是第三方侧滑框架 [BGASwipeBackLayout](https://github.com/bingoogolapple/BGASwipeBackLayout-Android) 在 Android 9.0 上面会[闪屏](https://github.com/bingoogolapple/BGASwipeBackLayout-Android/issues/173),并且还是 **100% 必现**,**用户体验极差**,我也跟作者反馈过这个问题,但结果不了了之,所以不得不移除。但是到了 [v10.0 版本](https://github.com/getActivity/AndroidProject/releases/tag/10.0),我又加上界面侧滑功能了,不过这次我换成了 [SmartSwipe](https://github.com/luckybilly/SmartSwipe) 来做,但是我又再一次失望了,这个框架在 Android 11 上面,如果 Activity 上有 WindowManager 正在显示,然后使用界面侧滑,那么会出现闪屏的情况,具体效果如下图:

![](picture/help/Swipe.jpg)

* 就这个情况我也联系过作者,并详细阐述了产生的原因和具体的复现步骤,但是我等了三天连个回复都没有,实属有些让我心寒,在等待的期间我看到 Github 的 issue 已经基本没有回复了,并且最后一次提交是在 13 个月前了,种种迹象都已经表明,所以经过慎重考虑,最终决定在 [v12.1 版本](https://github.com/getActivity/AndroidProject/releases/tag/12.1) 移除界面侧滑功能。

#### 为什么没有用今日头条的适配方案

* 关于屏幕适配方案,其实不能说头条的方案就是最好的,其实谷歌已经针对屏幕适配做了处理,就是 dp 和 sp ,而 dp 的计算转换是由屏幕的像素决定,系统只认 px 单位, dp 需要进行转换,比如 1dp 等于几个 px ,这个时候就需要基数进行转换,比如 1dp = 2px,这个基数就是 2。

@@ -146,7 +158,7 @@ ActivityXxxxBinding binding = DataBindingUtil.setContentView(this, R.layout.acti

* 显然这种方式是不合理的,也非常地不人性化。网上这种方案可能主要就是为了解决把控件宽高写死之后,在某些字体上显示比较大的机型会出现字显示不全的问题,而这种把控件宽高写死的方式本身也是不合理的,应该在不得已的情况下才把控件的宽高写死,一般情况下我们应当使用自适应的方式,让控件自己测量自己的宽高,特别是在有显示字体的控件下,就更不应该把宽高写死。

#### 为什么用 DialogFragment 来防止内存泄漏
#### 为什么没有用 DialogFragment 来防止内存泄漏

* DialogFragment 的出现就是为了解决 Dialog 和 Activity 生命周期不同步导致的内存泄漏问题,在 AndroidProject 曾经引入过,也经过了很多个版本的更新迭代,不过在 [10.0](https://github.com/getActivity/AndroidProject/releases/tag/10.0) 版本后就被移除了,原因是 Dialog 虽然有坑,但是 DialogFragment 也有坑,可以说解决了一个问题又引发了各种问题。先来细数 我在 DialogFragment 上踩过的各种坑:

@@ -158,7 +170,7 @@ ActivityXxxxBinding binding = DataBindingUtil.setContentView(this, R.layout.acti
* 看过这些问题,你是不是和我一样,感觉这 DialogFragment 不是一般的坑,不过最终我放弃了使用 DialogFragment,并不是因为 DialogFragment 又出现了新问题,而是我想到了更好的方案来代替 DialogFragment,方案就是 Application.registerActivityLifecycleCallbacks,想必大家现在已经猜到我想干啥,和 DialogFragment 的作用一样,通过监听 Activity 的方式来管控 Dialog 的生命周期,但唯一不同的是,它不会出现刚刚说过 DialogFragment 的那些问题,这种方式在 AndroidProject 上迭代了几个版本过后,这期间没有发现新的问题,也没有收到别人反馈过这块的问题,证明这种方式是可行的。

#### 为什么用腾讯 X5 WebView
#### 为什么没有用腾讯 X5 WebView

* 首先我问大家一个问题,腾讯出品的 X5 WebView 就一定比原生 WebView 好吗?我觉得未必,我依稀记得 Android 9.0 还是 Android 10 刚出来的时候,我点了升级按钮,然后就发现微信和 QQ 的网页浏览卡得让我怀疑人生,不过后面突然某一天就变好了,从这件事可以得出两点结论:

@@ -168,7 +180,7 @@ ActivityXxxxBinding binding = DataBindingUtil.setContentView(this, R.layout.acti

* 基于以上两点,我的个人建议是优先使用原生 WebView,如果不满足需求了,可以自行替换成 X5 WebView,当然不是说 X5 WebView 一定不好,用原生 WebView 一定就好,而是 AndroidProject 的目标是稳中求胜,另外一个是 AndroidProject 中有针对 WebView 做统一封装,后续替换成 X5 WebView 的成本还算是相对较低的。

#### 为什么用单 Activity 多 Fragment
#### 为什么没有用单 Activity 多 Fragment

* 这个问题在前几年是一个比较火热的话题,我表示很能理解,因为新鲜的事物总是能勾起人的好奇,让人忍不住试一试,但是我先问大家一个问题,单 Activity 多 Fragment 和写多个 Activity 有什么优点?大家第一个反应应该是每写一个页面都不需要在清单文件中注册了,但是这个真的是优点吗?我可以很明确地告诉大家,我已经写了那么多句代码,不差那句在清单文件注册的代码。那么究竟什么才是对我们有价值的?我觉得就两点,一是减少前期开发的工作量,二是降低后续维护的难度。所以省那一两句有前途吗?我们是差那一两句代码的人吗?如果这种模式能够帮助我们写好代码,这个当然是有价值的,非常值得一试的,否则就是纯属瞎扯淡。不仅如此,我个人觉得这种模式有很大的弊端,会引发很多问题,例如:

@@ -180,7 +192,7 @@ ActivityXxxxBinding binding = DataBindingUtil.setContentView(this, R.layout.acti
* 如果单 Activity 多 Fragment 不能为我们创造太大的价值时,这种模式根本就不值得我们去做,因为我们最终得到的,永远抵不上付出的。

#### 为什么用 ConstraintLayout 来写布局
#### 为什么没有用 ConstraintLayout 来写布局

* 大家如果有仔细观察的话,会发现 AndroidProject 其实没有用到 ConstraintLayout 布局,在这里谈谈我对这个布局的看法,约束布局有一个优点,没有布局嵌套,所以能减少测量次数,从而提升布局绘制的速度,但是优点也是它的缺点,正是因为没有布局嵌套,View 也就没有层级概念,所以它需要定义很多 ViewID 来约束相邻的 View 的位置,就算这个 View 我们在 Java 代码中没有用到,但是在约束布局中还是要定义。这样带来的弊端有几个:

@@ -200,9 +212,9 @@ ActivityXxxxBinding binding = DataBindingUtil.setContentView(this, R.layout.acti

* AndroidProject 其实一直有这样做,把很多组件都拆成了独立的框架,例如:权限请求框架 [XXPermissions](https://github.com/getActivity/XXPermissions),网络请求框架 [EasyHttp](https://github.com/getActivity/EasyHttp)、吐司框架 [ToastUtils](https://github.com/getActivity/ToastUtils) 等等,我都是将它抽离在 AndroidProject 之外,作为一个单独的开源项目进行开发和维护,至于说为什么还有一些代码没有抽取出来,主要原因有几点:

1. 和业务的耦合性高,例如 Dialog 组件引用了很多基类(BaseDialog、BaseAdapter)
1. 和业务的耦合性高,例如 Dialog 组件引用了很多项目的基类,例如 **BaseDialog**、**BaseAdapter** 等
2. 业务有定制化需求,因为 Dialog 的 UI 风格要跟随项目的设计走,所以你懂的
2. 业务有定制化需求,因为 Dialog 的 UI 风格要跟随项目的设计走,所以代码如果在项目中,修改起来会非常方便,如果抽取到框架中,要怎么修改和统一 UI 风格呢?我个人认为框架不适合做 UI 定制化,因为每个产品的设计风格都不一样,就算开放再多的 API 给外部调用的人设置 UI 风格,也无法满足所有人的需求。
* 基于以上几点,我并不认为所有的东西都适合抽取成框架给大家用,有些东西还是跟随 **AndroidProject** 一起更新比较好。当然像权限请求这种东西,我个人觉得抽成框架是比较合适的,因为它和业务的关联性不大,更重要的是,如果某一天你觉得 **XXPermissions** 做得不够好,你随时可以在 **AndroidProject** 替换掉它,并且整个过程不需要太大的改动。

@@ -220,7 +232,7 @@ ActivityXxxxBinding binding = DataBindingUtil.setContentView(this, R.layout.acti

* EventBus 我之前其实有加入过一版,只不过在 [v10.0](https://github.com/getActivity/AndroidProject/releases/tag/10.0) 版本上面移除了,原因很简单,它不是一个项目的必需品,我们用 EventBus 的初衷应该是,当需求在现有的基础上实现起来比较困难或者麻烦时,我们可以考虑用一用,但是到了实际项目中,会出现很多滥用的情况出现,在这里我建议大家,能用正常方式实现通讯的,尽量不要用 EventBus 实现。另外大家如果真的有需要,可以自行加入,集成也相对比较简单。

#### 为什么用 Retrofit 和 RxJava
#### 为什么没有用 Retrofit 和 RxJava

* 我想问大家一个问题,这两个框架搭配起来好用吗?可能大家的回答都不一致,但是我个人觉得不好用,接下来让我们分析一下 Retrofit 有什么问题:

@@ -268,7 +280,7 @@ ActivityXxxxBinding binding = DataBindingUtil.setContentView(this, R.layout.acti

* 原生的 RecyclerView.Adapter 本身就支持多 type,只需要重写适配器的 getItemType 方法即可,具体用法不做过多介绍。

#### 为什么用 Dagger 框架
#### 为什么没有用 Dagger 框架

* 框架的学习和使用成本极高,但总体收益不高,不适用于大部分人,所以不会考虑加入。

@@ -286,4 +298,4 @@ ActivityXxxxBinding binding = DataBindingUtil.setContentView(this, R.layout.acti

* 谈谈我对新技术的看法,首先我会思考这种新技术能解决什么痛点,这点非常重要,再好的技术创新,也必须得创造价值,否则就是在扯淡。有人肯定会问,什么样的技术才算有价值?对于我们 Android 程序员来讲,无非就围绕两点,开发和维护。要么在前期开发上,能发挥很大的作用,要么在后续维护上面,能体现它的优势。

* 还有谷歌的新技术不一定都是好的,也有一些是 KPI 的产物,别忘了,他们也是程序员,他们也有 KPI 考核,为了年终奖和晋升,他们不得不卖力宣传,纵使他们知道这个东西有硬伤,但是他们也会推出来看看市场反应。所以我们看待一种新技术,不要太看重是否是大公司出品的,也不要太看重是哪个行业名人写的,我们应该要重点关注的是,产品的质量以及能带给我们带来哪些帮助,这个才是正确的技术价值观。
* 还有谷歌的新技术不一定都是好的,也有一些是 **KPI 产物**,别忘了,他们也是打工的,他们也有 **KPI 考核**,为了年终奖和晋升,他们不得不卖力宣传,纵使他们知道这个东西有硬伤,但是他们也会推出来看看市场反应。所以我们看待一种新技术,不要太看重是否是大公司出品的,也不要太看重是哪个行业名人写的,我们应该要重点关注的是,产品的质量以及能带给我们带来哪些帮助,还有会带来哪些不好的影响,这个才是正确的技术价值观。

+ 0
- 4
app/build.gradle Datei anzeigen

@@ -182,10 +182,6 @@ dependencies {
implementation 'com.scwang.smart:refresh-layout-kernel:2.0.3'
implementation 'com.scwang.smart:refresh-header-material:2.0.3'
// 侧滑框架:https://github.com/luckybilly/SmartSwipe
implementation 'com.billy.android:smart-swipe:1.1.2'
implementation 'com.billy.android:smart-swipe-x:1.1.0'
// 日志打印框架:https://github.com/JakeWharton/timber
implementation 'com.jakewharton.timber:timber:4.7.1'

+ 35
- 4
app/src/main/AndroidManifest.xml Datei anzeigen

@@ -4,12 +4,10 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.hjq.demo">
<!-- 联网权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 网络状态 -->
<!-- 网络相关 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- 外部存储 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -206,4 +204,37 @@
</application>
<!-- Android 11 软件包可见性适配:https://www.jianshu.com/p/d1ccd425c4ce -->
<queries>
<!-- 拍照意图:MediaStore.ACTION_IMAGE_CAPTURE -->
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
<!-- 拍摄意图:MediaStore.ACTION_VIDEO_CAPTURE -->
<intent>
<action android:name="android.media.action.VIDEO_CAPTURE" />
</intent>
<!-- 图片裁剪意图 -->
<intent>
<action android:name="com.android.camera.action.CROP" />
</intent>
<!-- 打电话意图:Intent.ACTION_DIAL -->
<intent>
<action android:name="android.intent.action.DIAL" />
</intent>
<!-- 分享意图:Intent.ACTION_SEND -->
<intent>
<action android:name="android.intent.action.SEND" />
</intent>
<!-- 调起其他页面意图:Intent.ACTION_VIEW -->
<intent>
<action android:name="android.intent.action.VIEW" />
</intent>
</queries>
</manifest>

+ 3
- 2
app/src/main/java/com/hjq/demo/action/StatusAction.java Datei anzeigen

@@ -47,9 +47,10 @@ public interface StatusAction {
*/
default void showComplete() {
StatusLayout layout = getStatusLayout();
if (layout != null && layout.isShow()) {
layout.hide();
if (layout == null || !layout.isShow()) {
return;
}
layout.hide();
}

/**

+ 0
- 18
app/src/main/java/com/hjq/demo/action/SwipeAction.java Datei anzeigen

@@ -1,18 +0,0 @@
package com.hjq.demo.action;

/**
* author : Android 轮子哥
* github : https://github.com/getActivity/AndroidProject
* time : 2019/12/08
* desc : 界面侧滑意图
*/
public interface SwipeAction {

/**
* 是否使用界面侧滑
*/
default boolean isSwipeEnable() {
// 默认开启
return true;
}
}

+ 1
- 3
app/src/main/java/com/hjq/demo/app/AppActivity.java Datei anzeigen

@@ -13,7 +13,6 @@ import com.hjq.bar.TitleBar;
import com.hjq.base.BaseActivity;
import com.hjq.base.BaseDialog;
import com.hjq.demo.R;
import com.hjq.demo.action.SwipeAction;
import com.hjq.demo.action.TitleBarAction;
import com.hjq.demo.action.ToastAction;
import com.hjq.demo.http.model.HttpData;
@@ -29,8 +28,7 @@ import okhttp3.Call;
* desc : 业务 Activity 基类
*/
public abstract class AppActivity extends BaseActivity
implements ToastAction, TitleBarAction,
SwipeAction, OnHttpListener<Object> {
implements ToastAction, TitleBarAction, OnHttpListener<Object> {

/** 标题栏对象 */
private TitleBar mTitleBar;

+ 1
- 11
app/src/main/java/com/hjq/demo/app/AppApplication.java Datei anzeigen

@@ -16,11 +16,9 @@ import androidx.core.content.ContextCompat;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;

import com.billy.android.swipe.SmartSwipeBack;
import com.hjq.bar.TitleBar;
import com.hjq.bar.initializer.LightBarInitializer;
import com.hjq.demo.R;
import com.hjq.demo.action.SwipeAction;
import com.hjq.demo.aop.DebugLog;
import com.hjq.demo.http.glide.GlideApp;
import com.hjq.demo.http.model.RequestHandler;
@@ -76,7 +74,7 @@ public final class AppApplication extends Application {
* 初始化一些第三方框架
*/
public static void initSdk(Application application) {
// 设置权限请求调试模式
// 设置调试模式
XXPermissions.setDebugMode(AppConfig.isDebug());

// 初始化吐司
@@ -161,14 +159,6 @@ public final class AppApplication extends Application {
// 启用配置
.into();

// Activity 侧滑返回
SmartSwipeBack.activitySlidingBack(application, activity -> {
if (activity instanceof SwipeAction) {
return ((SwipeAction) activity).isSwipeEnable();
}
return true;
});

// 初始化日志打印
if (AppConfig.isLogEnable()) {
Timber.plant(new DebugLoggerTree());

+ 3
- 2
app/src/main/java/com/hjq/demo/manager/DialogManager.java Datei anzeigen

@@ -84,11 +84,12 @@ public final class DialogManager implements LifecycleEventObserver, BaseDialog.O
*/

@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, @NonNull Lifecycle.Event event) {
if (event != Lifecycle.Event.ON_DESTROY) {
return;
}
source.getLifecycle().removeObserver(this);
DIALOG_MANAGER.remove(lifecycleOwner);
lifecycleOwner.getLifecycle().removeObserver(this);
clearShow();
}
}

+ 2
- 1
app/src/main/java/com/hjq/demo/manager/InputTextManager.java Datei anzeigen

@@ -306,8 +306,9 @@ public final class InputTextManager implements TextWatcher {

/**
* 输入发生了变化
*
* @return 返回按钮的 Enabled 状态
*/
boolean onInputChange(InputTextManager helper);
boolean onInputChange(InputTextManager manager);
}
}

+ 0
- 1
app/src/main/java/com/hjq/demo/ui/activity/CameraActivity.java Datei anzeigen

@@ -80,7 +80,6 @@ public final class CameraActivity extends AppActivity {
}
if (XXPermissions.isGrantedPermission(this, new String[]{Permission.MANAGE_EXTERNAL_STORAGE, Permission.CAMERA})
&& intent.resolveActivity(getPackageManager()) != null) {

File file = getSerializable(IntentKey.FILE);
if (file == null) {
toast(R.string.camera_image_error);

+ 0
- 5
app/src/main/java/com/hjq/demo/ui/activity/CrashActivity.java Datei anzeigen

@@ -239,11 +239,6 @@ public final class CrashActivity extends AppActivity {
}
}

@Override
public boolean isSwipeEnable() {
return false;
}

@Override
public void onBackPressed() {
// 按返回键重启应用

+ 0
- 5
app/src/main/java/com/hjq/demo/ui/activity/GuideActivity.java Datei anzeigen

@@ -49,11 +49,6 @@ public final class GuideActivity extends AppActivity {
mIndicatorView.setViewPager(mViewPager);
}

@Override
public boolean isSwipeEnable() {
return false;
}

@SingleClick
@Override
public void onClick(View view) {

+ 0
- 5
app/src/main/java/com/hjq/demo/ui/activity/HomeActivity.java Datei anzeigen

@@ -156,9 +156,4 @@ public final class HomeActivity extends AppActivity
mViewPager.setAdapter(null);
mBottomNavigationView.setOnNavigationItemSelectedListener(null);
}

@Override
public boolean isSwipeEnable() {
return false;
}
}

+ 0
- 5
app/src/main/java/com/hjq/demo/ui/activity/ImagePreviewActivity.java Datei anzeigen

@@ -138,11 +138,6 @@ public final class ImagePreviewActivity extends AppActivity
return false;
}

@Override
public boolean isSwipeEnable() {
return false;
}

/**
* {@link ViewPager.OnPageChangeListener}
*/

+ 0
- 5
app/src/main/java/com/hjq/demo/ui/activity/LoginActivity.java Datei anzeigen

@@ -359,9 +359,4 @@ public final class LoginActivity extends AppActivity
}
return false;
}

@Override
public boolean isSwipeEnable() {
return false;
}
}

+ 0
- 5
app/src/main/java/com/hjq/demo/ui/activity/RegisterActivity.java Datei anzeigen

@@ -240,11 +240,6 @@ public final class RegisterActivity extends AppActivity
return false;
}

@Override
public boolean isSwipeEnable() {
return false;
}

/**
* 注册监听
*/

+ 0
- 5
app/src/main/java/com/hjq/demo/ui/activity/SplashActivity.java Datei anzeigen

@@ -90,11 +90,6 @@ public final class SplashActivity extends AppActivity {
//super.onBackPressed();
}

@Override
public boolean isSwipeEnable() {
return false;
}

@Override
protected void initActivity() {
// 问题及方案:https://www.cnblogs.com/net168/p/5722752.html

+ 1
- 7
app/src/main/java/com/hjq/demo/ui/activity/VideoPlayActivity.java Datei anzeigen

@@ -11,7 +11,6 @@ import androidx.annotation.NonNull;
import com.gyf.immersionbar.BarHide;
import com.gyf.immersionbar.ImmersionBar;
import com.hjq.demo.R;
import com.hjq.demo.action.SwipeAction;
import com.hjq.demo.app.AppActivity;
import com.hjq.demo.other.IntentKey;
import com.hjq.demo.widget.PlayerView;
@@ -25,7 +24,7 @@ import java.io.File;
* desc : 视频播放界面
*/
public final class VideoPlayActivity extends AppActivity
implements SwipeAction, PlayerView.onPlayListener {
implements PlayerView.onPlayListener {

private PlayerView mPlayerView;
private VideoPlayActivity.Builder mBuilder;
@@ -90,11 +89,6 @@ public final class VideoPlayActivity extends AppActivity
.hideBar(BarHide.FLAG_HIDE_BAR);
}

@Override
public boolean isSwipeEnable() {
return false;
}

/**
* 播放参数构建
*/

+ 10
- 3
app/src/main/java/com/hjq/demo/ui/dialog/UpdateDialog.java Datei anzeigen

@@ -155,7 +155,7 @@ public final class UpdateDialog {
String channelId = "";
// 适配 Android 8.0 通知渠道新特性
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(getString(R.string.update_notification_channel_id), getString(R.string.update_notification_channel_name), NotificationManager.IMPORTANCE_HIGH);
NotificationChannel channel = new NotificationChannel(getString(R.string.update_notification_channel_id), getString(R.string.update_notification_channel_name), NotificationManager.IMPORTANCE_LOW);
channel.enableLights(false);
channel.enableVibration(false);
channel.setVibrationPattern(new long[]{0});
@@ -165,6 +165,7 @@ public final class UpdateDialog {
}

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getContext(), channelId)
// 设置通知时间
.setWhen(System.currentTimeMillis())
// 设置通知标题
.setContentTitle(getString(R.string.app_name))
@@ -174,7 +175,9 @@ public final class UpdateDialog {
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.launcher_ic))
// 设置通知静音
.setDefaults(NotificationCompat.FLAG_ONLY_ALERT_ONCE)
// 设置震动频率
.setVibrate(new long[]{0})
// 设置声音文件
.setSound(null)
// 设置通知的优先级
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
@@ -204,6 +207,8 @@ public final class UpdateDialog {

@Override
public void onProgress(File file, int progress) {
mUpdateView.setText(String.format(getString(R.string.update_status_running), progress));
mProgressView.setProgress(progress);
// 更新下载通知
notificationManager.notify(notificationId, notificationBuilder
// 设置通知的文本
@@ -212,10 +217,10 @@ public final class UpdateDialog {
.setProgress(100, progress, false)
// 设置点击通知后是否自动消失
.setAutoCancel(false)
// 是否正在交互中
.setOngoing(true)
// 重新创建新的通知对象
.build());
mUpdateView.setText(String.format(getString(R.string.update_status_running), progress));
mProgressView.setProgress(progress);
}

@Override
@@ -230,6 +235,8 @@ public final class UpdateDialog {
.setContentIntent(PendingIntent.getActivity(getContext(), 1, getInstallIntent(), Intent.FILL_IN_ACTION))
// 设置点击通知后是否自动消失
.setAutoCancel(true)
// 是否正在交互中
.setOngoing(false)
.build());
mUpdateView.setText(R.string.update_status_successful);
// 标记成下载完成

+ 26
- 18
app/src/main/java/com/hjq/demo/widget/StatusLayout.java Datei anzeigen

@@ -65,20 +65,22 @@ public final class StatusLayout extends FrameLayout {
initLayout();
}

if (!isShow()) {
// 显示布局
mMainLayout.setVisibility(VISIBLE);
if (isShow()) {
return;
}
// 显示布局
mMainLayout.setVisibility(VISIBLE);
}

/**
* 隐藏
*/
public void hide() {
if (mMainLayout != null && isShow()) {
//隐藏布局
mMainLayout.setVisibility(INVISIBLE);
if (mMainLayout == null || !isShow()) {
return;
}
//隐藏布局
mMainLayout.setVisibility(INVISIBLE);
}

/**
@@ -96,23 +98,25 @@ public final class StatusLayout extends FrameLayout {
}

public void setIcon(Drawable drawable) {
if (mLottieView != null) {
// 这里需要先将 Lottie 动画禁用掉
mLottieView.setAnimation(0);
if (mLottieView.isAnimating()) {
mLottieView.cancelAnimation();
}
mLottieView.setImageDrawable(drawable);
if (mLottieView == null) {
return;
}
if (mLottieView.isAnimating()) {
mLottieView.cancelAnimation();
}
mLottieView.setImageDrawable(drawable);
}

/**
* 设置提示动画
*/
public void setAnimResource(@RawRes int id) {
if (mLottieView != null) {
mLottieView.setAnimation(id);
// 这里需要调用播放动画,否则会出现第一次显示动画效果正常,第二次显示动画会不动
if (mLottieView == null) {
return;
}

mLottieView.setAnimation(id);
if (!mLottieView.isAnimating()) {
mLottieView.playAnimation();
}
}
@@ -125,9 +129,13 @@ public final class StatusLayout extends FrameLayout {
}

public void setHint(CharSequence text) {
if (mTextView != null && text != null) {
mTextView.setText(text);
if (mTextView == null) {
return;
}
if (text == null) {
text = "";
}
mTextView.setText(text);
}

/**

+ 4
- 4
app/src/main/res/values/strings.xml Datei anzeigen

@@ -19,13 +19,13 @@
<string name="common_network_error">当前网络不可用,请检查网络设置</string>
<string name="common_phone_input_hint">输入手机号码</string>
<string name="common_phone_input_hint">输入手机号码</string>
<string name="common_phone_input_error">手机号输入不正确</string>
<string name="common_password_input_error">请输入密码</string>
<string name="common_password_input_unlike">两次密码输入不一致,请重新输入</string>
<string name="common_code_input_hint">输入验证码</string>
<string name="common_code_input_hint">输入验证码</string>
<string name="common_code_send">发送验证码</string>
<string name="common_code_send_hint">验证码已发送,请注意查收</string>
<string name="common_code_error_hint">验证码错误,请检查输入</string>
@@ -229,7 +229,7 @@
<string name="image_select_max_hint">本次最多只能选择 %d 张图片</string>
<string name="image_select_error">无法选中,该图片已经被除</string>
<string name="image_select_error">无法选中,该图片已经被除</string>
<!-- 视频选择 -->
<string name="video_select_title">视频选择</string>
@@ -239,7 +239,7 @@
<string name="video_select_max_hint">本次最多只能选择 %d 个视频</string>
<string name="video_select_error">无法选中,该视频已经被除</string>
<string name="video_select_error">无法选中,该视频已经被除</string>
<!-- 拍照 -->
<string name="camera_launch_fail">无法启动相机</string>

+ 2
- 2
build.gradle Datei anzeigen

@@ -1,5 +1,5 @@
// AndroidProject 版本:v12.0
// 发布日期:2021 年 02 月 22
// AndroidProject 版本:v12.1
// 发布日期:2021 年 02 月 27
buildscript {
repositories {

BIN
picture/help/swipe.jpg Datei anzeigen


+ 7
- 0
widget/src/main/java/com/hjq/widget/layout/SettingBar.java Datei anzeigen

@@ -5,6 +5,7 @@ import android.content.res.TypedArray;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
@@ -59,6 +60,12 @@ public final class SettingBar extends FrameLayout {
mLeftView.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
mRightView.setGravity(Gravity.END | Gravity.CENTER_VERTICAL);

mLeftView.setSingleLine(true);
mRightView.setSingleLine(true);

mLeftView.setEllipsize(TextUtils.TruncateAt.END);
mRightView.setEllipsize(TextUtils.TruncateAt.END);

mLeftView.setLineSpacing(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()), mLeftView.getLineSpacingMultiplier());
mRightView.setLineSpacing(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()), mRightView.getLineSpacingMultiplier());


Laden…
Abbrechen
Speichern