在Android开发中,由于Android碎片化严重,屏幕分辨率千奇百怪,而想要在各种分辨率的设备上显示基本一致的效果,适配成本越来越高。
先来介绍下基本概念
1、分辨率:
分辨率就是手机屏幕的像素点数,“宽×高”,安卓手机屏幕常见的分辨率有480×800、720×1280、1080×1920等。
2、屏幕大小:
屏幕大小是手机对角线的物理尺寸,以英寸(inch)为单位。比如5寸手机,对角线的尺寸:5寸×2.54厘米/寸=12.7厘米。
3、px(Pixel):
设备真实像素,同一像素值在不同分辨率的手机上展示不同,分辨率越大,展示区域越小
4、dpi(Dots Per Inch):
每英寸面积内的像素点数,计算方式如下。
比如我的手机,华为mate9: dpi = √﹙1080 * 1080 + 1920 * 1920﹚/ 5.9 = 373
比如 Google Pixel2 : dpi = √﹙1080 * 1080 + 1920 * 1920﹚/ 5.0 = 440
4.5寸手机:dpi = √﹙1080 * 1080 + 1920 * 1920﹚/ 4.5 = 440
5、density: 屏幕密度,density = dpi/160
6、dp(Device Independent Pixels):
设备独立像素,每英寸160px的设备上,1dp = 1px;以此类推,每英寸320px的设备上,1dp = 2px。
dp = px / density
dp = px * (160 / dpi) => 1dp = 2px * ( 160 / 320)
7、dp和px转换关系
- px = density * dp;
- density = dpi / 160;
- px = (dpi / 160) * dp;
系统屏幕密度:
- ldpi文件夹下对应的密度为120dpi,对应的分辨率为240*320
- mdpi文件夹下对应的密度为160dpi,对应的分辨率为320*480
- hdpi文件夹下对应的密度为240dpi,对应的分辨率为480*800
- xhdpi文件夹下对应的密度为320dpi,对应的分辨率为720*1280
- xxhdpi文件夹下对应的密度为480dpi,对应的分辨率为1080*1920
通过dp加上自适应布局和weight比例布局可以基本解决不同手机上适配的问题,这基本是最原始的Android适配方案。
我原以为这样就够了,但是这只能保证我们写出来的界面适配绝大部分手机,部分手机仍然需要单独适配,为什么dp只解决了90%的适配问题?因为并不是所有的1080P的手机dpi都是160的整数倍,比如Google 的Pixel2(1920 * 1080)的dpi是420,也就是说,在Pixel2中,1dp=2.625px,这样会导致相同分辨率的手机中,一个100dp * 100dp的控件,在一般的1080P手机上(dpi是480)展示是300px,而Pixel 2 中只有262.5px,这样控件的实际大小会有所不同。
图一是1080P、480dpi的手机,图二是1080P、420dpi的手机,设置图片宽度为360dp
图一占据px: 360dp * ( 480dpi / 160) = 1080 px 刚好满屏
图二占据px: 360dp * ( 420dpi / 160) = 945 px 未满屏
原理同上,也是通过DisplayMetrix.density 来进行dp转换, 通过DisplyMetrix.scaledDensity来进行sp转换
TypedValue#applyDimension()
华为Mate 9的屏幕尺寸是5.9英寸,分辨率是1920×1080像素。
经过计算并不是160的整数倍,373/160 = 2.3 , 通过系统调用发现density = 3.0,不知道为啥? 也许是手机厂商设置的480?。
至于1920 和1808是手机的虚拟导航键的问题,展示了虚拟导航键,size就变化了。