前言
◾官方方案
◾宽高限定符:
◾AndroidAutoLayout:
◾今日头条方案
◾SmallestWidth
基本概念 ◾屏幕像素密度:
一块屏幕物理区域内像素数量越多像素密度越大,被称为dpi(每英寸所含像素数量)
◾像素无关密度(dp):
为什么提出: 同样屏幕大小的设备,像素点不同,如果用px做单位就会出现高分辨率下控件大,低分辨率下控件小的问题
官方方案
缺陷
设备的宽度的dpi有大有小
同样写200dp
左480dpi 右560dpi
宽高限定符适配
以某一个分辨率为基准
现在我们以320×480的分辨率为基准:
◾将屏幕的宽度分为320份,取值为x1~x320
◾将屏幕的高度分为480份,取值为y1~y480
注意事项: x160 表示的是3分之一 写一个正方形 不能用x160,y160,需要用x160,x160
缺点:xml文件过多(本身分辨率多,一些厂商rom可以显示隐藏虚拟按键,又增加了更多不同的分辨率),增加了apk大小
AndroidAutoLayout库
缺点:
1.支持的属性有限
◾layout_width
◾layout_height
◾layout_margin(left,top,right,bottom)
◾pading(left,top,right,bottom)
◾textSize
◾maxWidth, minWidth, maxHeight, minHeight
2.需要扩展很多view
今日头条的适配方案
density 的意思就是 1 dp 占当前设备多少像素
设备 1,屏幕宽度为 1080px,480DPI
因为在160dpi下 1dp =1px
所以480dpi下 1dp=3px
屏幕宽度就是 1080px/3=360dp
设备2
560dpi下 1dp=3.5px
屏幕宽度就是 1440px/3.5=411dp
可以看到屏幕的总 dp 宽度在不同的设备上是会变化的,但是我们在布局中填写的 dp 值却是固定不变的
在布局中我们写却写的是相同的dp
想象一下 同样写180dp两个view横着并排,第一个设备可以占满,第二个设备却还留着白边
所以要想做到写相同的dp 在不同宽度设备上 显示宽度百分比一致 就要将设备宽度统一
当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density
几个例子
假设设计图是375dp的, 则在375dp 的设计图中一个view 宽度为100dp
以 1080px 宽的设备为例 ,
设计图中
view 宽度占比 100/375=0.267
1080设备中
view宽 1080/375*100 =288px
所占比例 288px/1080=0.267
以1440px 设备为例
设计图中view 宽度占比 100/375=0.267
1440设备中
view宽 1440/375*100 =384px
所占比例 384px/1440=0.267
优势:
复杂度很低,表现优异
缺点:
引用了第三方库,而第三方库的设计图和我方设计图宽度差距非常大时,会导致比例偏差过大
举例说明:
第三方设计库750dp宽度的设计图
100dp的view 在设计图上仅占 100/750=0.133
经过修改density在设备上占比 则会是其 2倍 0.267
解决方案
1: 使用其他不常用尺寸 例如pt 计算公式对pt 使用,则对原第三方库中dp 不会产生影响, 比例偏差不会差距太大
2:以activity 为单位使用别的适配方案
SmallestWidth
宽高限定符的升级版
samlleest 最小宽度 含义是指 不管屏幕旋转与否 都取屏幕最小的一个边作为 最小宽度
两个公式
density=dpi/160
px/density=dp
以 1920 * 1080、480 dpi 为例
宽度为1080 则 dp 为 1080/480*160=360dp
则系统会取 values-sw360dp 文件夹下的dimens.xml
dimen的生成过程
以一个宽度为基准值 生成其他宽度
以360dp为例,屏幕分成了360份,则每一份所占dp如下图所示
生成400dp则是
这样可以保证所有设备中 dp_360都可以占满屏幕宽度,所使用的view占屏幕宽度的百分比也是一样的
即使没有精准适配也会找到最相近的values-swdp 文件夹,有误差但是仍可以较为完美的实现适配
缺点:
1.使用sp需要单独生成sp的文件
2.增加app体积,但这一点比宽高限定符要小得多
自动生成工具
github.com/wildma/Scre…
最后感谢观看