Android屏幕适配方案之头条适配—AutoSize
荒废了几天继续我的每日一篇学习博客 go go go!
介绍下目前(我认为)主流的适配方案
前言:
首先,我们应该明白没有完美的适配方案,因为安卓设备真的是五花八门,宽高比差距太大,在保证页面View不变形的情况下,只能取宽度为基准,自适应的设置高度,这样造成的页面整体高度会超出屏幕高度,解决的方法就只能是设置页面滚动,避免页面内容显示不全;其次要是以高度为基准,很大情况下view会变形,比如图片什么的会被拉伸变形。
- 头条的适配方案优化版——AndroidAutoSize;
- SmallestWidth 限定符适配方案;
- 约束布局——ConstraintLayout;
以上是目前普遍使用的适配方案,还有一些适配方案也可以了解下,指不定你就接手了一个老项目,里面就是这些方案之一,了解一下不吃亏,不过一定程度上这些方案存在缺点和不足,所以慢慢的淡出实际开发,但是看你的需求还是有一定的可取之处。比如
- 对适配要求不是很高的:dp直接适配:dp是google推荐的适配UI尺寸单位,通过控件的自适应和权重可以基本解决大部分手机的适配,成本最低,但是对于一些复杂Ui和dpi差距很大的手机型号,这套适配方案就存在很大的不足了。
- dimens适配(称呼很多,暂时我就称呼为dimens适配吧):实际就是把你需要适配的所有手机的宽高像素列举出来,设定一个基准的分辨率值,计算出不同宽高手机的dimens值,不同宽高比去对应自身对应的dimens文件,精准高效的适配。但是这存在一个很大的缺点就是,目前国内安卓厂商五花八门,尺寸根本没有一个限定,很难穷举所有设备的分辨率。
- 鸿洋大神的AndroidAutoLayout 适配框架:这套适配在三五年前还是热门的,在手机宽高差距不那么天差地别,宽高比差距不是很明显的时代,这套适配能完美的通过规定的宽高比来同比缩放控件的大小,能达到完美复原设计UI图的效果。但是现在的手机这就明显不适用了,图片等会出现明显的拉伸变形。
头条方案适配的原理
这里准备白嫖下大佬的,自己也是跟着大佬学习了这个适配方案。
先上链接:https://juejin.im/post/5b7a29736fb9a019d53e7ee2
还得明白,今日头条适配方案默认项目中只能以高或宽中的一个作为基准,进行适配。
此适配方案依赖density的计算,换算公式:
设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density
意思就是UI设计图标注的1dp占当前设备的多少像素。
借鉴下别人的描述:
densityDpi:设备的DPI,也就是上面那些常量值,是由手机厂商设置的。
density:缩放系数,这个下面会详细讲解。
scaledDensity:字体缩放系数,和density一样,不过可以受用户设置的字体大小的偏好进行
1、densityDpi:
dpi的计算:
dpi=(√(横向分辨率^2+纵向分辨率^2))/屏幕尺寸
emmmm,虽然我是学数学的,但是我还是想说这玩意看着就不是一眼出答案那种,还是需要计算一波
public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;
public static int DENSITY_DEVICE = getDeviceDensity();
private static int getDeviceDensity() {
return SystemProperties.getInt("qemu.sf.lcd_density",
SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
}
代码可以看出来,densityDpi是通过系统自己的属性取值,如果qemu.sf.lcd_density 的值取不到,就取 ro.sf.lcd_density的,还取不到,就使用默认值,也就是 160 了。一般都是手机厂商设置好的,我们可以直接获取到设备的dpi
2、density
用设备DPI除以(设计图)基准DPI,就可以得到缩放系数,跟上面“设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density”的计算是一样的。
例如:你手机是640320分辨率的,你设计图自定义或者设计的尺寸就是640320的,那么在这个手机设备上,density就是1,相当于设计图尺寸在手机设备上的缩放系数是1;
3、scaledensity
与 density 一样的,也是缩放系数,默认情况和 density 的值是相等的。
scaledDensity = density;
下面开始说头条方案如何适配的:
Android中在布局文件中填写的是什么单位,最后都会被转化为 px,所以看看下面的typevalue的源码:
public static float applyDimension<