Android开发过程当中咱们经常使用的尺寸单位有px、dp,还有一种sp通常是用于字体的大小。可是因为px是像素单位,好比咱们一般说的手机分辨例如1920*1080都是px的单位。如今Android屏幕分辨率碎片化720x1280、1080x1920、2280x1080,这就形成例如187px会在各个分辨率的机型上都是显示同样大小的,那确定不是咱们想要的效果,因此用px单位咱们是难以达到适配效果的,那么为何用dp能够呢?android
使用px单位从左到右依次为 480 * 800、1080 * 1920、1440 * 2560api
使用dp单位从左到右依次为 480 * 800、1080 * 1920、1440 * 2560bash
屏幕总宽度依次为 320dp、415dp、411dppost
dp指的是设备独立像素,以dp为尺寸单位的控件,在不一样分辨率和尺寸的手机上表明了不一样的真实像素,好比在分辨率较低的手机中,可能1dp=1px,而在分辨率较高的手机中,可能1dp=2px,这样的话,一个187dp高度的控件,在不一样的手机中就能表现出差很少的大小了。性能
android中的dp在渲染前会将dp转为px,计算公式:学习
px = density * dp;字体
density = dpi / 160;spa
px = dp * (dpi / 160);插件
而dpi是根据屏幕真实的分辨率和尺寸来计算的,每一个设备均可能不同的。设计
因为density不是固定不变的,因此每一个分辨率不一样的设备他们的density都确定不相等,这样就会形成每一个设备的宽/高对应的总dp都是不一样的,假设480 * 800分辨率的density是1.5,1080 * 1920分辨率的density是2.6,1440 * 2560分辨率的density是3.5。那么它们对应的宽度总dp = (宽度px) / density,分别为320dp、415dp、411dp。能够看出单位为dp的时候三个设备之间的差距就不是很大了,可是这样确定仍是不能知足咱们对屏幕适配的要求的。下面来看看Android常见的三种比较成熟的屏幕适配方案,并分析这几种方案的优劣。
设定一个基准的分辨率,也就是设计图对应的分辨率,其余分辨率都根据这个基准分辨率来计算,在不一样的尺寸文件夹内部,根据该尺寸编写对应的dimens文件。
好比咱们的设计图 375 * 667为基准分辨率
宽度为375,将任何分辨率的宽度整分为375份,取值为x1-x375
高度为667,将任何分辨率的高度整分为667份,取值为y1-y667
那么对于1080*1920的分辨率的dimens文件来讲,
x1=(1080/375)*1=2.88px
x2=(1080/375)*2=5.76px
y1=(1920/667)*1=2.87px
y2=(1920/667)*2=5.75px
当代码里面引用高度为y_187,在APP运行时会根据当前设备分辨率去找对应xml文件中对应的高度,咱们就能够按照设计稿上的尺寸填写相对应的dimens引用了,这样基本解决了咱们的适配问题,并且极大的提高了咱们UI开发的效率。
简单经过计算验证下这种方案是否能达到适配的效果,例如设计图上有一个宽187dp的View。
480 * 800
设计图占宽比: 187dp / 375dp = 0.498
实际在480 * 800占宽比 = 187 * 1.28px / 480 = 0.498
1080 * 1920
设计图占宽比: 187dp / 375dp = 0.498
实际在1080 * 1920占宽比 = 187 * 2.88px / 1080 = 0.498
计算高同理
可是这个方案有一个致命的缺陷,那就是须要精准命中才能适配,好比1920x1080的手机就必定要找到1920x1080的限定符,不然就只能用统一的默认的dimens文件了。而使用默认的尺寸的话,UI就极可能变形,简单说,就是容错机制不好。
smallestWidth适配,或者叫sw限定符适配。指的是Android会识别屏幕可用高度和宽度的最小尺寸的dp值(其实就是手机的宽度值),而后根据识别到的结果去资源文件中寻找对应限定符的文件夹下的资源文件。
这种机制和上文提到的宽高限定符适配原理上是同样的,都是系统经过特定的规则来选择对应的文件。
能够把 smallestWidth 限定符屏幕适配方案 当成这种方案的升级版,smallestWidth 限定符屏幕适配方案 只是把 dimens.xml 文件中的值从 px 换成了 dp,原理和使用方式都是没变的
├── src/main
│ ├── res
│ ├── ├──values
│ ├── ├──values-sw320dp
│ ├── ├──values-sw360dp
│ ├── ├──values-sw400dp
│ ├── ├──values-sw411dp
│ ├── ├──values-sw480dp
│ ├── ├──...
│ ├── ├──values-sw600dp
│ ├── ├──values-sw640dp
复制代码
1920 * 1080分辨率的手机,dpi为420,咱们一样设置一个View为187dp宽
1440 * 2560分辨率的手机,dpi为560,咱们一样设置一个View为187dp宽
由于识别的文件夹是values-sw410dp的文件夹,可是屏幕宽度为415dp和411dp,因此最后计算出的占比会有一点点偏差,基本能够忽略不计,能够达到相对比较准确的适配效果
今日头条屏幕适配方案的核心原理在于,根据如下公式算出 density
默认px = density * dp,也就是屏幕总宽度dp = 屏幕宽度px / density,这个时候咱们假设全部设备上的屏幕总宽度dp会等于咱们设计图375dp,那么能够得出一个公式:
density = 屏幕宽度px / 设计图宽度(375dp)
而后咱们经过系统api,将density赋值给系统,抛弃掉系统默认计算density的计算公式。
这样能够很巧妙的实现屏幕适配,并且侵入性极低,甚至能够忽略不计。
1920 * 1080分辨率的手机,咱们一样设置一个View为187dp宽,设计图宽度为375dp
1440 * 2560分辨率的手机,咱们一样设置一个View为187dp宽,设计图宽度为375dp
能够看出,这种方案是彻底没有偏差的,并且侵入性极低,只须要修改系统的density。虽然修改系统的density属性会产生一小部分影响,可是基本都是很好解决的。