JessYanCoding / AndroidAutoSize

🔥 A low-cost Android screen adaptation solution (今日头条屏幕适配方案终极版,一个极低成本的 Android 屏幕适配方案).

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

JessYanCoding opened this issue · comments

在这里陈列的内容是 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);

commented

补充一个, 假设 Design Size On AndroidManifest 是 667 * 375, 需横屏 Activity 进入竖屏 Activity, 但是竖屏 Activity 布局异常(过大), 那么在竖屏 Activity 的 onCreateView (不是 onCreate )里补充 AutoSize.autoConvertDensity(this, 375, false);即可

为了保证其他使用者阅读常见问题时的阅读质量,这里不允许随便留言,只允许留言带有解决方案的 AndroidAutoSize 或 今日头条屏幕适配方案的问题,有什么有疑问,请重新开启新的 Issues,并按规则完善 Issues 信息,否则留言会被删除!

@GSEVE 有问题就提新 Issues,或者在 意见收集区 中留言,上面已经写了这里只接受问题和解决方案的留言,其他留言都会被删除

@xiaoxiaScut 你提的 issues 已经回复你了,这里不允许留言与解决方案无关的留言

are you kidding me?你依赖工程的问题

are you kidding me?你依赖工程的问题

sorry,重启了一下工程重新编译就好了~不知道为啥一定要重新打开才行。。

commented

使用之后,toolbar 的 navigationicon 不居中

commented

华为v8适配貌似没用。。黑鲨1代 vivo 基本都行 到了华为v8就显示不全了。。。变的特别大 怎么办?

大哥,小弟已近走投无路,无奈选择这个框框,可是。。。。可是。。。。。我掉进了不可自拔的陷阱,这个框框就是BUG的集合体,为了解决适配,而使用适配,可是因为使用了适配,要解决一大堆适配,这哪是头条的适配方案,这是坑爹集团董事长的坑坑业务啊

个人觉得本款适配方案算是比较简单也比较轻量级的吧,至于你说的关于使用这款适配之后造成了你自己之前适配的问题你这里没具体说明你之前的适配是依据怎样的原理实现的,所以我也不是很好说,另外你说这个框架是BUG集合体,感觉你也应该具体说明BUG在哪里啊。。

@love-311 大神我可以加您微信吗,您帮帮帮我,我的微信935312568

不是什么大神,我也帮不了你,框架我个人使用觉得还是挺不错的,所以多看看是不是自己的问题,另外看看自己对于这个框架是否理解到了吧~

@LJFDBXJ 兄弟,你的心情我能理解,我本人也希望这个项目越来越完善,问题越来越少,但任何项目都不可能保证百分之百没有任何问题,即然是开源项目,那就是需要大家共同提出意见,以及指出问题所在,让大家都可以参与其中,这样才能保证开源项目能不断完善。

这个项目,我本是出于自己的好意,贡献了这个项目,甚至连所有文档和注释,也是竭尽所能做的足够完善,我怕大家找不到相应问题的解决方案,还专门把所有问题都集中到这个 issues 中,方便大家查找,我并没有收大家的任何好处,所以如果你觉得这个项目有任何问题,请指出问题所在,我会感激你指出的问题,并积极的去修复,但你没必要以 “BUG的集合体” 这种词汇来诋毁这个项目。

如果你觉得这个项目已经达到了 完全没法用 这个地步,你大可以不用,去选择其他更完美的屏幕适配方案,这对我们没有任何影响。

任何开源项目作者,都只是出于自己的好意提供工具给大家使用,他们并没有这个义务为大家提供免费服务,如果你觉得不好,你可以提意见,你也可以选择不使用,抱怨起不到任何作用。

很抱歉,没有意识到我的用词态度,给您带来不便,辛苦了,有总比没有好,没有诋毁的意思,希望谅解,确实抱怨起不到任何作用,在这里向您表达我的歉意。不能@您了,显示您处于Busy状态。Thank you for your contribution

你好,请问下,加上之后为什么会卡顿,界面有个筛选吸顶的功能,然后自定义了个scrollView

我们设计的每个页面的 Width 是 750, Height 可能是变化的,有时1300+、有时1400+、有时1500+,有没有指定某个页面区别于默认的设置

commented

如果是系统的CheckBox和RadioButton这样的按钮,右侧的图片如何让它显示成正常大小

commented

坑爹集团董事长的坑坑业务

其实我也是这么觉得,三方库和有的手机简直无解

项目是平板项目,UI图是1920px*1200px,横屏显示,所有的Activity都在清单文件中限制为横屏了,我在HUAWEI T1-823L平板上,一切正常,当屏幕进入熄屏状态后,再恢复,发现平板有一个由竖屏切换到横屏的过程,我的布局是ListView嵌套ListView,被嵌套的那层ListView的item布局,发现它适配失效了,这个有解决的参考吗

什么时候支持androidX

@JasonYinH 一直都支持,框架做了 support 和 AndroidX 的 兼容处理,如果项目依赖 support 就使用 support,如果依赖 AndroidX 就使用 AndroidX

在小米中的ListView 不管加啥 都会错位

main (native): tid=1 systid=20891
#00 pc 0x4b4cc libc.so
#1 pc 0x1af9c0 libart.so
#2 pc 0x66a228 libart.so
#3 pc 0x66a018 libart.so
at android.content.res.AssetManager.nativeGetResourceIdentifier(Native method)
at android.content.res.AssetManager.getResourceIdentifier(AssetManager.java:791)
at android.content.res.ResourcesImpl.getIdentifier(ResourcesImpl.java:281)
at android.content.res.Resources.getIdentifier(Resources.java:2164)
at me.jessyan.autosize.utils.ScreenUtils.getStatusBarHeight(ScreenUtils.java:43)
at me.jessyan.autosize.AutoSizeConfig.init(AutoSizeConfig.java:250)
at me.jessyan.autosize.AutoSizeConfig.init(AutoSizeConfig.java:205)
at me.jessyan.autosize.InitProvider.onCreate(InitProvider.java:44)
at android.content.ContentProvider.attachInfo(ContentProvider.java:2451)
at android.content.ContentProvider.attachInfo(ContentProvider.java:2421)
at android.app.ActivityThread.installProvider(ActivityThread.java:7509)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:7032)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6921)
at android.app.ActivityThread.access$1600(ActivityThread.java:269)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2045)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:233)
at android.app.ActivityThread.main(ActivityThread.java:7959)
at java.lang.reflect.Method.invoke(Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)

感谢,usb插拔造成的适配失效,通过上面的方法得到解决

commented

针对双屏异显,搞了个工具类替换 Presentation 后,可以使双屏异显支持该屏幕适配方案
相关 Issues:#188 #278 #393

Java 版本:SecondaryDisplayHelper.java
Kotlin 版本:SecondaryDisplayHelper.kt

commented

某些版本的Android11和Android12以后。会存在如下问题:

  1. APP进入页面A(竖屏)
  2. 点击“跳转页面B”进入页面B(横屏)
  3. 返回页面A
  4. 点击“弹窗”,弹窗C出现。弹窗出现以后:此时ResourcesImpl的updateConfiguration函数被调用了。
    mMetrics.setTo(metrics),resource的metrics被系统修改回默认值了。
  5. 关闭弹窗C,再次点击“弹窗”。显示异常。

折叠屏、平行视窗、分屏及悬浮窗参考方案

这个链接并没有解决什么问题,折叠屏在平行视窗的情况下设置的density与实际的并不一样,猜测在这种情况下可能是系统篡改了density,怎么解决呢?