-
Notifications
You must be signed in to change notification settings - Fork 2k
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
getResources() 也不能解决所有问题,导致屏幕适配失效的另外一种原因以及解决方案 #299
Comments
大佬好,当我在父布局中设置 父布局 的 generateLayoutParams(AttributeSet)时 app没有出现适配失效的问题,但在xml中不能预览布局,点开错误和警告信息出现: java.lang.IllegalArgumentException: you must set design_width_in_dp in your AndroidManifest file at me.jessyan.autosize.utils.Preconditions.checkArgument(Preconditions.java:39) at me.jessyan.autosize.AutoSizeConfig.getDesignWidthInDp(AutoSizeConfig.java:432) at me.jessyan.autosize.AutoSizeCompat.autoConvertDensityOfGlobal(AutoSizeCompat.java:54) at com.basic.modular.view.widget.AutoSizeLinearLayout.generateLayoutParams(AutoSizeLinearLayout.java:27) at com.basic.modular.view.widget.AutoSizeLinearLayout.generateLayoutParams(AutoSizeLinearLayout.java:11) at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:1125) at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1097) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084) at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:1126) at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1097) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084) at android.view.LayoutInflater.inflate(LayoutInflater.java:682) at android.view.LayoutInflater.inflate(LayoutInflater.java:501) |
override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams { |
没有设置desiginInDp吗?
…------------------ Original ------------------
From: "JessYanCoding/AndroidAutoSize" ***@***.***>;
Date: Wed, Mar 22, 2023 06:37 PM
***@***.***>;
***@***.******@***.***>;
Subject: Re: [JessYanCoding/AndroidAutoSize] getResources() 也不能解决所有问题,导致屏幕适配失效的另外一种原因以及解决方案 (#299)
大佬好,当我在父布局中设置 父布局 的 generateLayoutParams(AttributeSet)时 app没有出现适配失效的问题,但在xml中不能预览布局,点开错误和警告信息出现:
java.lang.IllegalArgumentException: you must set design_width_in_dp in your AndroidManifest file at me.jessyan.autosize.utils.Preconditions.checkArgument(Preconditions.java:39) at me.jessyan.autosize.AutoSizeConfig.getDesignWidthInDp(AutoSizeConfig.java:432) at me.jessyan.autosize.AutoSizeCompat.autoConvertDensityOfGlobal(AutoSizeCompat.java:54) at com.basic.modular.view.widget.AutoSizeLinearLayout.generateLayoutParams(AutoSizeLinearLayout.java:27) at com.basic.modular.view.widget.AutoSizeLinearLayout.generateLayoutParams(AutoSizeLinearLayout.java:11) at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:1125) at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1097) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084) at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:1126) at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1097) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084) at android.view.LayoutInflater.inflate(LayoutInflater.java:682) at android.view.LayoutInflater.inflate(LayoutInflater.java:501)
override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams {
if (!isInEditMode) {
try {
val context = this.context
if (context is CustomAdapt) {
AutoSizeCompat.autoConvertDensityOfGlobal(super.getResources())
AutoSizeCompat.autoConvertDensity(super.getResources(), context.sizeInDp, context.isBaseOnWidth)
}
} catch (ignored: Exception) {}
}
return super.generateLayoutParams(attrs)
}
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
在RecyclerView的requestLayout也加下
|
我在 #13 中提到过,由于 DisplayMetrics#density 在整个程序运行期间都是 public 公有的,所有不光是 AndroidAutoSize 可以修改它的值,系统、三方库、以及其他代码,也都有权限修改它的值,一旦在某个页面绘制之前,DisplayMetrics#density 的值不是经过 AndroidAutoSize 计算过的正确值,那就会出现屏幕适配失效的问题。
只要 DisplayMetrics#density 的值在某个页面绘制之前,保证是经过 AndroidAutoSize 计算过的正确值,那就能大概率保证屏幕适配能够正常完成,所以我们现在的终极解决方案就是在页面显示到屏幕上的 0.0000000000000000000000000001 秒之前,将 DisplayMetrics#density 修改为正确的值,所以我们的解决方案是在 getResources() 中,重新设置 DisplayMetrics#density。
由于在系统中所有参与单位转换的场景中都会调用 getResources() 方法,所以这就能保证 DisplayMetrics#density 的值始终是正确的。
但是接到一些 issues 的反馈,在实际开发中,即使重写 getResources() 也可能会导致屏幕适配失效,这里先抛开一些新手,由于不理解今日头条屏幕适配最基本的知识,而导致的适配问题。
我在这就谈谈即使在页面绘制的 0.0000000000000000000000000001 秒之前,保证 DisplayMetrics#density 的值为正确值,绘制出来的页面可能会屏幕失效吗?
答案是,有可能的,使用 XML 编写布局的项目可能会有这个问题。
关于适配失效的原因,这里就要谈到,关于系统源码层的东西,我在这里就简单说一下。
在 Activity#onCreate 中将页面的 Layout ID 传给 setContentView 方法后,其实不是立即进行页面绘制的,系统需要将 XML 的节点全部解析出来,并通过反射生成对应的 View 对象,在创建 View 对象的过程中需要创建 LayoutParams,并将 XML 中声明的 Width、Height、Margin 等属性全部存储到 LayoutParams 当中,在 View OnMeasure 时,会用到这个 LayoutParams 来确定 View 各个属性最终的值。
所以在 Activity#onCreate setContentView() 时,只是保证将 XML 中声明的 View 节点,全部转化为 View 对象,并将 XML 中声明的 View 属性全部保存在这个 View 对象中,这个页面的绘制还是要等到 ViewRootImpl 执行 performTraversals() 时才能完成。
View 对象的生成和页面完成绘制是有时间间隔的,在生成 View 对象,创建 LayoutParams 时,保存的 Width、Height、Margin 等属性是按照当时的 DisplayMetrics#density 计算的,如果在创建 LayoutParams 时 DisplayMetrics#density 的值不是正确值,这会导致 LayoutParams 中保存的 Width、Height、Margin 等属性的值也不是正确值,但是在 View onMeasure 中的默认逻辑,又会直接使用 LayoutParams 中保存的属性值,所以即使你在 onMeasure 之前保证 DisplayMetrics#density 是正确的值,也可能会出现适配失效的问题。
所以如果你的项目是通过 XML 来编写布局,你应该保证在 LayoutParams 创建时,DisplayMetrics#density 为正确值,所以解决方案是,重写 父布局 的 generateLayoutParams(AttributeSet),并在方法中设置正确的 DisplayMetrics#density, 注意是 父布局
以上是我分析系统源码时,发现的可能会导致屏幕失效的问题,给的这个解决方案,可能会解决你的问题,也可能解决不了,如果能解决你的问题,望留言告知,这个解决方案配合 getResources() 应该就比较稳定了。
如果还是解决不了你的问题,那就需要你自己打断点,具体问题具体分析了,看看是从 setContentView 到 onMeasure 的哪个阶段出现了问题,今日头条屏幕适配方案也就 DisplayMetrics#density 是公有可被随时修改,这一个问题,当然这个特性也给我们带来了很多便利,你们反馈的所有问题其实都是这一个问题导致的,只不过是不同的呈现方式而已,如果所有方案都解决不了适配失效,那就重写 onMeasure,自己测量,重写 onMeasure 是可以百分百解决所有适配问题的,只不过需要你有一定基础。
The text was updated successfully, but these errors were encountered: