Android 屏幕适配 - chuwuwang/ReadingNote GitHub Wiki
https://github.com/ningsk/enjoy-everyday/issues/25
- px = density * dp
- density = dpi / 160
- px = dp * (dpi / 160)
而dpi是根据屏幕真实的分辨率和尺寸计算的,每个设备都可能是不一样的
因为density不是固定不变的,所以每个分辨率不同的设备的density都肯定不相等,所以我们需要去做屏幕适配。
1、smallestWidth限定符方案
该方案是通过识别屏幕可用宽度和高度的最小尺寸的dp值,然后根据识别的结果去资源文件中寻找对应限定符的文件夹下的资源文件。
举个例子,小米5的dpi是480,横向像素是1080px,根据px = dp(dpi/160),可知,横向的dp值是1080/(480/160) = 360dp。系统会去寻找是否存在value-sw360dp的文件夹以及对应的资源文件。
|---src/main
| |---res
| |---|---values
| |---|---values-sw320dp
| |---|---values-sw360dp
| |---|---values-sw400dp
| |---|---values-sw411dp
| |---|---...
| |---|---values-sw640dp
smallestWidth限定符适配和宽高限定符适配最大的区别是,前者有很好的容错机制,如果没有value-sw360dp文件夹,系统会向下寻找,比如离360dp最近的只有value350dp,那么Android会选择value-sw350dp文件夹下面的资源文件,这个特性完美了解决了宽高限定符的容错问题。
ps 宽高限定符方案:穷举市面上所有的Android手机的像素值:
参考资料:
|---src/main
| |---res
| |---|---values
| |---|---values-800x480
| |---|---values-860x540
| |---|---values-1024x600
| |---|---values-1024x768
| |---|---...
| |---|---values-2560x1440
设置一个基准分辨率,其他的分辨率根据这个基准分辨率来计算,不同尺寸的文件夹下,根据该尺寸编写相对应的dimens。
比如以480x320为基准分辨率:
- 宽度为320,将任何分辨率的宽度整分为320份,取值为x1-x320
- 高度为480,将任何分辨率的高度整分为480分,取值为y1-y480
那么对于800x480的分辨率的dimens文件来说
x1 = (480/320) * 1 = 1.5px
x2 = (480/320) * 2 = 3.0px
2、 今日头条的方案(动态修改density)
今日头条屏幕适配方案的核心原理在于,根据以下公式算出 density。
默认px = density * dp,也就是屏幕总宽度dp = 屏幕宽度px / density,这个时候我们假设所有设备上的屏幕总宽度dp会等于我们设计图375dp,那么可以得出一个公式:
density = 屏幕宽度px / 设计图宽度(375dp)
然后我们通过系统api,将density赋值给系统,抛弃掉系统默认计算density的计算公式。
这样可以很巧妙的实现屏幕适配,而且侵入性极低,甚至可以忽略不计。
验证方案
1920 * 1080分辨率的手机,我们同样设置一个View为187dp宽,设计图宽度为375dp。
density = (屏幕宽度px = 1080) / 375 = 2.88
View宽度 = density * 187dp = 538.56
算出占屏幕宽度的比例,57.6 / 1080 = 0.498
1440 * 2560分辨率的手机,我们同样设置一个View为187dp宽,设计图宽度为375dp。
density = (屏幕宽度px = 1440) / 375 =3.84
View宽度 = density * 187dp = 718.08
算出占屏幕宽度的比例,718.08 / 1440 = 0.498
可以看出,这种方案是完全没有误差的,而且侵入性极低,只需要修改系统的density。
虽然修改系统的density属性会产生一小部分影响,但是基本都是很好解决的。
https://github.com/JessYanCoding/AndroidAutoSize