目的:搞成和设计图一样的比例,适配的终极目的就是按比例适配

本质就是这个公式:

px = density * dp;

每个手机的像素数量是不变的,所以通过改变1dp所占的像素个数(像素密度),达到使不同设备的横向dp值相等,从而实现了比例适配

 

今日头条最终:在某些条件下保证比例相等例(成比例):

注意这个比例相等是指控件在设备上的大小和设备的比例,在不同设备上相同,同时也和设计图上的控件和设计图的比例相等。
在两个设备的总dp值相等时,可以达到等比例的效果(猜测一开始谷歌也是想在出产手机的时候也按这个标准),所以今日头条就改变density来使总dp值相等来达到比例适配。

那为什么两个设备的dp值相等了就成比例了呢?

只有我们开发时用的是dp,那两个设备的dp值相等时才能达到了成比例的效果,我们设置1dp就是整个设备的1/dp值,例如设备的dp值是360dp,因为dp和长度挂钩,那1dp就是1/360设备的长度.

 

今日头条的做法是在同一个dp值下如360dp,改变density的值,因为屏幕宽度是固定的所以通过改变density的值来使设备的dp值为同一个值。

按照上述公式:

px = density * dp;

density = dpi / 160;

改变density其实就是在改变dpi。

以上是今日头条适配的实质,用autoSize的三方库

dp的推出解决了什么问题。

1.在理想情况下:dp能保证在不同设备上尺寸相等(前提是dpi是物理dpi不是Google给的规定dpi,只有dpi是物理dpi才能保证dp在不同设备上尺寸相等),如果各大厂商都按照一个尺寸(必须一个尺寸)去生产设备,并且dpi是物理实际api(在现实中并不是物理dpi,而是Google给了一个范围规定,下面给出),很简单的就达到了适配效果,因为屏幕尺寸固定,dp的尺寸也固定。

2.dp为什么能够保证在不同设备上尺寸相等

理论:

1dp的尺寸=像素点大小*1dp的像素数 经过公式变换也就是:像素点的大小*(dp值*dpi的值/160)=1/dpi*(1dp*dpi/160)=1/160

这个公式成立的前提是dpi是真实的物理dpi

例子:

我们知道了:dpi是每英寸像素点数,px是像素点数,那我有60px的实际物理长度不就是(60/dpi)英寸嘛,1px的实际长度就是 1/dpi 英寸咯。可以得到公式:长度 L(英寸) = px /  dpi。手机的dpi不同,那1px的物理长度其实就不同。

 dip其实为了达到展示一样物理长度才弄出来的一个概念,最后还是需要转换成像素来显示的。

为了让每部手机上dip都显示一样物理长度,那只需要dip和px转换满足关系:dip = n * px /dpi (n > 0)。那么

px = dip * dpi / n。设备通过这样的对应关系来决定显示的像素值,这样显示出的像素值不同,而保证物理长度相同了。

我们来算一下看。比如20dip的长度:先计算20dip对应的px为20 * dpi /n,物理长度为 px / dpi = (20 * dpi / n) /dpi = 20/n(英寸)。n是一个固定值,那么对于所有设备来说, 20 dip都会显示成 20/n 英寸长的像素。

Android将这个n值定为160。这个值设为160,是因为第一款Android设备(HTC的T-Mobile G1)是属于160dpi。

那么,当设备dpi为160时,1px = 1dip。
 

3.什么是物理dpi,什么是Google给的dpi有什么影响

dpi的定义上面写的很清楚,算法也是给出一个例子:

我们以一个 4.95 英寸 1920 * 1080 的 nexus5 手机设备为例:

计算:物理dpi,用这个实际设备计算的物理dpi是能保证dp的长度固定的。

  1. 计算直角边像素数量: 19202+10802=2202^2(勾股定理)。
  2. 计算 DPI:2202 / 4.95 = 445。
  3. 得到这个设备的 DPI 为 445 (每英寸的距离中有 445 个像素)。

计算:dp

  • 先明白一个概念,所有显示到屏幕上的图像都是以 px 为单位。
  • Dip 是我们开发中使用的长度单位,最后他也需要转换成 px。
  • 计算这个设备上 1dip 等于多少 px:
    px = dip x dpi /160
    px = 1 x 445 / 160 = 2.78
  • 通过上面的计算可以看出在此设备上 1dip = 2.78px,那么这是一个真实的故事吗? nonono,其中的关键值 dpi 并不是我们算出来的 445 ,请往下看。

Android 系统定义的 Dpi


上面计算的 445Dpi 是在 4.95 英寸下的 1920*1080 手机,那如果是 4.75 分辨率下的呢? 4.55 分辨率下的呢?。。。。可见是很麻烦的,同一个分辨率在不同的屏幕尺寸上 Dpi 也不相同。为了省事,解决这个问题, Android 中内置了几个默认的 Dpi ,在特定的分辨率下自动调用,也可以手动在配置文件中修改。

 

ldpi

mdpi

hdpi

xhdpi

xxhdpi

分辨率

240x320

320x480

480x800

720x1280

1080x1920

系统dpi

120

160

240

320

480

基准比例

0.75

1

1.5

2

3

这是内置的 Dpi ,啥意思? 在 1920*1080 分辨率的手机上 默认就使用 480 的 dpi ,不管的你的尺寸是多大都是这样。

说到底,因为有dpi这个动态的系数,我们在使用dp的时候才能兼容不同分辨率的设备。

到这里,应该都明白了 dpi 的由来,以及系统 dpi 跟物理 dpi 并不一定相同。在系统中使用的全部都是系统 dpi,没有使用物理 dpi,也获取不到物理 dpi。物理 dpi 主要用于厂家对于手机的参数描述(也可以看做 ppi )!

 

 

引申问题dp为什么是一个物理单位又不是一个物理单位?

物理单位的定义是一个单位长度是固定的。
是物理单位:在理想的状态下大家如果都按照:Google最开始的制造标准 (使用物理dpi)去出产手机那每个dp的长度是固定的1/160确实是一个物理长度单位
不是物理单位:因为手机系统使用的的dpi并不是物理dpi,所以dp的长度不再固定所以就不能说dp是一个物理长度单位