Skip to content

JessYan: 今日头条屏幕适配方案常见问题汇总,提问前必看! #13

Open
@JessYanCoding

Description

@JessYanCoding

在这里陈列的内容是 AndroidAutoSize 框架和 今日头条屏幕适配方案 的常见 Issues 以及解决方案,如果在这里没找到您需要的答案,不妨前往 历史 Issues 碰碰运气

这里会持续更新 今日头条屏幕适配方案 的相关问题以及解决方案,如果您发现有什么重要的与 今日头条屏幕适配方案 相关的已知或未知的问题在这里未收录,都可以通过留言或者新增 Issues 的方式告知我,并不仅限于 AndroidAutoSize 框架的问题,不管您是不是使用 AndroidAutoSize 框架,我们都可以共同出力,让 今日头条屏幕适配方案 更完善、更稳定!

+ 如果你想用好 AndroidAutoSize,少出问题,请认真看完下面的所有文字,不要嫌字数长,拒绝做伸手党!!!


Tips: 今日头条适配方案的原理来源于修改 DisplayMetrics#density,因为 DisplayMetrics#density 是全局的,所以只要 DisplayMetrics#density 一经修改,项目中的所有页面、所有控件都可以奏效,包括三方库控件和系统控件,这就是今日头条屏幕适配方案天然拥有优于其他屏幕适配方案的低成本和低侵入性

但 DisplayMetrics#density 是公有的,谁都有权限修改,AndroidAutoSize 可以把 DisplayMetrics#density 修改成一个可以完成屏幕适配的值,其他三方库、Android 系统、以及项目成员就可以把 DisplayMetrics#density 修改或恢复成另一个值,这都将导致屏幕适配的失效,特别是在某些定制系统上,因为这个定制系统做的某些特殊操作都是未知的 (但 AndroidAutoSize 开源这么久,大多数系统都是很稳定的)

但这个问题 AndroidAutoSize 却无能为力,因为 DisplayMetrics#density 是公有的,AndroidAutoSize 只不过是修改 DisplayMetrics#density 中的一员,系统并没有赋予 AndroidAutoSize 可以锁死 DisplayMetrics#density 为某一特定值的权限,而只要其他代码拥有修改 DisplayMetrics#density 的权限,就有不稳定性的产生

所以该问题目前唯一的解决方案就是确保在页面显示到屏幕上的 0.0000000000000000000000000001 秒之前,将 DisplayMetrics#density 修改为期望的值,哪怕页面显示完的后一秒,DisplayMetrics#density 又被修改为其他值,只要这个页面不重建,就不会影响已经显示了的页面,也就是下面的第一个解决方案

+ 以下内容是大部分 issues 出现的核心原因,本框架上手容易,但是要想真正的驾驭,需要熟悉其中的原理!


由于 DisplayMetrics#density 在整个 Application 中是公有并且唯一的,所以并不存在在每一个 Activity 或者 Fragment 中都拥有一个独立的 DisplayMetrics#density,框架之所以能实现每个 Activity 或 Fragment 都可以拥有不同的设计图尺寸,是因为框架自动在每个 Activity 或 Fragment 显示 UI 之前将 DisplayMetrics#density 更改为了它期望的正确值,但是框架并不知道项目中的每个 UI 需要显示或更新到屏幕上的正确时机,只是默认在 setContentView() 之前修改了 DisplayMetrics#density,但在实际开发中,业务何其复杂,有些时候 UI 的显示或更新并不只局限于 setContentView(),比如说在某些业务中会出现一些自定义事件触发自定义 View 进行 requestLayout() 、invalidate() ,或者 RecyclerView 在某些时机需要再次更新 Item 中的内容,但要注意的是,在所有会影响 UI 显示的方法之前都应该保证 DisplayMetrics#density 切换到正确的值,如果框架在你的自定义事件中并未在 UI 显示或更新前将 DisplayMetrics#density 设置为期望的值,就会出现屏幕适配异常的问题,请你辅助框架在 UI 显示或更新之前调用 AutoSize 中的方法,将 DisplayMetrics#density 更改为期望的值。

但如果你对框架原理不是非常熟悉,请不要频繁的更改 DisplayMetrics#density(更改设计图尺寸,以及横竖屏切换都会导致 DisplayMetrics#density 的更改),如果又不懂原理,又喜欢更改 DisplayMetrics#density,那就有一定概率出现你们经常在 issues 中提到的一些屏幕适配失效或者异常的问题,这有很大概率是因为你们自己不懂原理又瞎鸡巴乱搞导致的!出现这个问题的原因就是因为更改 DisplayMetrics#density 后导致期望的 DisplayMetrics#density 与实际的 DisplayMetrics#density 不一致,什么叫懂原理?请把 骚年你的屏幕适配方式该升级了! 系列文章都看一遍,再认真看下 AndroidAutoSize 中核心类的源码,别问我核心类是哪些,问就是全部!

一般情况下,下面的 万能解决方案 就能解决大部分的问题,因为在每个与 UI 相关的方法执行时,都会调用 getResources() 方法, 但这个解决方案只能保证一个 Activity 只存在一个设计图尺寸,如果你的一个 Activity 出现了多个设计图尺寸,比如说嵌入了系统 View、第三方 View (系统 View 或第三方 View 的设计图尺寸有很大概率和你项目的设计图尺寸不一致)或者不同设计图尺寸的 Fragment,那这个 万能解决方案 也不能解决所有问题。

  • 万能解决方案,看这里!!! 这里要感谢 Blankj 老师提供的解决方案,在任何情况下本来适配正常的布局突然出现适配失效,适配异常等问题,只要重写 Activity 的 getResources() 方法即可,如果是 Dialog、PopupWindow 等控件出现适配失效或适配异常,同样在每次 show() 之前调用 AutoSize#autoConvertDensity() 即可
    @Override
    public Resources getResources() {
        //需要升级到 v1.1.2 及以上版本才能使用 AutoSizeCompat
        AutoSizeCompat.autoConvertDensityOfGlobal(super.getResources());//如果没有自定义需求用这个方法
        AutoSizeCompat.autoConvertDensity(super.getResources(), 667, false);//如果有自定义需求就用这个方法
        return super.getResources();
    }
  • 新的解决方案,当 getResources() 失效时可以试试,重写 父布局 的 generateLayoutParams(AttributeSet) 方法,具体内容请看 这里
@Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        AutoSizeCompat.autoConvertDensityOfGlobal(getResources());//如果没有自定义需求用这个方法
        AutoSizeCompat.autoConvertDensity(getResources(), 667, false);//如果有自定义需求就用这个方法
        return super.generateLayoutParams(attrs);
    }

  • 如果想让 AndroidAutoSize 适配多个进程的页面,请在 App 初始化时调用 AutoSize#initCompatMultiProcess(Context)AutoSize#checkAndInit(Application),像 这样(有些插件化框架可能会默认开启多进程)

  • 使用代码布局或者创建自定义控件时,在工具类 AutoSizeUtils 中,使用对应的方法,将其他单位转换为 px,作为控件尺寸,即可完成屏幕适配

  • 如果不想让 App 内的字体大小跟随系统设置中字体大小的改变,请调用 AutoSizeConfig.getInstance().setExcludeFontScale(true); 即可

  • 如果想适配 Bitmap,需要在创建 Bitmap 时指定修改后的 DisplayMetrics
    Bitmap bitmap = Bitmap.createBitmap(activity.getResources().getDisplayMetrics(),width,height,config);

Metadata

Metadata

Assignees

No one assigned

    Labels

    importantRequires attention

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions