前言:大家都知道"dp"这个单位,在Android上画布局时使用,用来取代px,使得画出的控件能够在不同手机上展示出相图的效果。记得有人这样跟我描述过:某个dp长度的一条线,在一个手机上展示是1cm,在其他手机上都会展示为1cm。dp是如何工作让不同屏幕手机展示“相同效果”呢?上面对dp展示的描述是否准确呢?
答案是并不是这样。
参考资料:
https://www.jianshu.com/p/5678f23faed3
强烈建议看这篇文章: https://www.jianshu.com/p/cd66b7e01d4a
https://www.cnblogs.com/H-BolinBlog/p/5647548.html
百度百科
1.屏幕基础概念
像素(px):是指在由一个数字序列表示的图像中的一个最小单位,称为像素。
分辨率(Resolution):这里指物理分辨率,是液晶屏最高可显示的像素数。
dpi(Dots Per Inch,每英寸点数):每英寸的像素点数。
density:每平方英寸像素点数。大多数手机x轴方向的dpi和y轴方向dpi是相同的,从概念上可以得出desity = dpi * dpi。如果手机屏幕面积为s,则density = Resolution / s,dpi = √density = √(Resolution / s)。
dip(Device Independent Pixels,设备独立像素):基于计算机控制的坐标系统和抽象像素(虚拟像素),由底层系统的程序使用,转换为物理像素的应用。
脑补“dip”计算过程:
如果要保持dip达到物理长度上一直,只需要dip和px满足关系:dip = n * px /dpi (n > 0)。
那么 dip = n * px / √density = n * px / √(Resolution / s)。
Android将这个n值定为160。这个值设为160,是因为第一款Android设备(HTC的T-Mobile G1)是属于160dpi。
那么,当设备dpi为160时,1px = 1dip。
2.dip的值
通过上面脑补的计算过程,可以让dip使用者达到不同手机显示相同效果。对于同样的px,每个设备的dip与设备的分辨率和面积相关。
实际,Android在dip和px进行换算时做了个偷懒,它内置了几个默认的 dpi ,在特定的分辨率下自动调用,忽略考虑设备的尺寸。
分辨率 dpi 基准比例
ldpi 240x320 120 0.75
mdpi 320x480 160 1
hdpi 480x800 240 1.5
xhdpi 720x1280 320 2
xxhdpi 1080x1920 480 3
手机中的 /system/build.prop 文件中有一行定义了系统使用的dpi:
ro.sf.lcd_density=480
可以看出系统中提供的dpi和设备屏幕的物理dpi并不相同。
可以通过以上代码获取系统提供的屏幕信息:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
介绍DisplayMetrics中的一些成员变量:
// 设备的基准比例,density = dpi / 160
// (这里的density仅代表基准比例,与我们上面基础概念中的density并不相同,注意不要混淆)
// px = density * dip
density
// 系统提供的dpi
// density = densityDpi / 160
// px = densityDpi * dip /160
densityDpi
如此,可以得出结论,Android中dip可以根据屏幕就分辨率动态适配为合适的px。由于没有考虑屏幕尺寸,使得相同dip在不同手机上并不能达到完全相同的物理效果。