Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
JessYanCoding opened this issue Aug 22, 2018 · 34 comments
Labels
important Requires attention

Comments

@JessYanCoding
Copy link
Owner

JessYanCoding commented Aug 22, 2018

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

@JessYanCoding JessYanCoding changed the title JessYan: 常见 Issues JessYan: 常见 Issues,提问前必看! Aug 23, 2018
@fredsun
Copy link

fredsun commented Sep 3, 2018

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

Repository owner deleted a comment from MrLeeys Sep 26, 2018
@JessYanCoding JessYanCoding added the important Requires attention label Oct 19, 2018
@JessYanCoding JessYanCoding changed the title JessYan: 常见 Issues,提问前必看! JessYan: 今日头条屏幕适配方案常见问题,提问前必看! Oct 19, 2018
@JessYanCoding JessYanCoding changed the title JessYan: 今日头条屏幕适配方案常见问题,提问前必看! JessYan: 今日头条屏幕适配方案常见问题汇总,提问前必看! Oct 19, 2018
@JessYanCoding
Copy link
Owner Author

JessYanCoding commented Nov 1, 2018

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

@JessYanCoding
Copy link
Owner Author

JessYanCoding commented Jan 7, 2019

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

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

Repository owner deleted a comment from CangJieStore Jan 7, 2019
Repository owner deleted a comment from xiaoxiaScut Jan 7, 2019
Repository owner deleted a comment from zxcvluyang Jan 7, 2019
@M78Code
Copy link

M78Code commented Jun 18, 2020

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

@JasonYinH
Copy link

什么时候支持androidX

@JessYanCoding
Copy link
Owner Author

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

@chenfan1227
Copy link

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

@JessYanCoding
Copy link
Owner Author

@chenfan1227 #59 (comment)

@billdizl
Copy link

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)

@xiaoxiaScut
Copy link

xiaoxiaScut commented Mar 28, 2022 via email

@whyrookie
Copy link

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

@xiaoxiaScut
Copy link

xiaoxiaScut commented Jun 14, 2022 via email

@Vixb1122
Copy link

Vixb1122 commented Aug 7, 2022

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

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

@xiaoxiaScut
Copy link

xiaoxiaScut commented Aug 7, 2022 via email

@JessYanCoding
Copy link
Owner Author

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

@xiaoxiaScut
Copy link

xiaoxiaScut commented Sep 29, 2022 via email

@billdizl
Copy link

billdizl commented Oct 11, 2022 via email

@zhangchuanchuan
Copy link

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

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

@xiaoxiaScut
Copy link

xiaoxiaScut commented Apr 17, 2023 via email

@jokerrou
Copy link

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

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

@xiaoxiaScut
Copy link

xiaoxiaScut commented May 17, 2023 via email

@jokerrou
Copy link

jokerrou commented May 17, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
important Requires attention
Projects
None yet
Development

No branches or pull requests