notice: 首先记住我手机的配置.
我的手机 小米M1
分辨率为 480px * 854px
屏幕密度 240dpi
屏幕大小 4.0英寸
1。名词解释:
dpi :(Dots Per Inch),指每英寸的像素,是衡量打印机打印精度的主要参数之一。
ppi:PPI(Pixel Per Inch)表示数字影像的解析度 (也许这样太过于抽象,你可以这样理解 dpi 就是 ppi)
分辨率: 例如 480 * 854 就是说 我的屏幕宽度有 480个像素点 ,高度有 854个像素点。
屏幕大小: 例如我的是4.0 英寸, 就是指 从屏幕的左上角 到 屏幕的右下角 连线长度为4.0英寸(可以换成厘米)
px: 像素单位。最基础的图像构成元素单位。
dp: Android发明的长度单位,具体的下边会说。
2。原因解释:
我们为什么会产生分辨率和屏幕密度的困扰?
注意上图:对于一个 宽度为5px 的线,我们希望在不同的手机上表现效果像上面的图一样吗?
我是这样认为的,我们期望的效果并不是如上图那样的,我们希望5px的线在B屏幕上被缩放,和屏幕A中一样的比例。
如下图:
我们期望的,往往是这种效果,所以这条线在屏幕B上,不能是5px,但是具体是多少px呢? 现在我们是不知道的,不如我们来动手算算吧~各位是不是都跃跃欲试了?
我们设定,屏幕B中的线长度为 X px。 设定屏幕A总宽度为 At ,屏幕B总宽度为Bt。
So,我们来比一下吧!
所以,我们的X可以推导出来:
这样,我们就可以计算出,在B屏幕上,这条线要画多长,才可以维持比例。
现在我们来做一个疯狂的假设吧,来死狗。
屏幕A 为谷歌定义的标准屏幕,谷歌为了让图像在各个屏幕上显示的比例相同,程序会为我们自动计算B屏幕中线的长度。(用上述公式计算)
现在我们来反推一下,我们用别的手机(密度不同,可以认为是屏幕B),在屏幕上画一条线,这条线应该在谷歌标准的屏幕上占多长呢?
首先,我们必须明白一点: 一个屏幕,对于宽度,有两重含义。
一种宽度叫做像素宽度:即 横向排列的像素点一共有多少个。 例如 480 * 854的手机,我的像素宽度就为 480
一种宽度叫做物理宽度:即 我的手机横向到底有多少厘米。 我的手机是4.0英寸屏幕,高宽比是16:9,勾股定理求出,我的物理宽度是1.9英寸。
所以,上面的At,Bt 并不能用宽度来表示,我们必须用一个更加公平的量来表示,有点像物理学的密度。所以,上图中的At,Bt应该为两种屏幕的密度。屏幕密度的求法文章最后再讲述。
好的,看到这里,我们来转换一下上面的公式和假设。
由于屏幕A是谷歌规定的官方标准,所以我们可以查阅资料得知:
屏幕A的参数:
分辨率 320 * 480
屏幕密度 160
我们来计算一下,我们的手机(即屏幕B上)同样的线段,应该在屏幕A上展示的宽度为多少?
设我们的手机上,所要展示的宽度为Y,设在谷歌的屏幕需要展示的宽度为X,设A的屏幕密度(谷歌规定的密度)为Ad,设B的屏幕密度(不同于规定密度的设备)为Bd,公式如下:
文字总结一下上图,最终公式为 X = Y(线段宽度) / (B屏幕密度 / A屏幕密度)
这样看是不是很眼熟? 对的!你没看错!X的单位就是谷歌规定的 dp!
所以X的单位就是dp!
公式也可以写成
1. dp = px (线段宽度的单位) / density
2. density = Bd / Ad;
由于谷歌与规定,标准的dpi为160,所以最终公式就推导出来了!
dp = px / ( dpi / 160)
这个公式到底有什么意义呢?
好的,我这里就和大家做一个小计算。
我的手机信息dpi为240,宽度为480px,高度为854px.
所以,我的手机宽高各是多少dp呢?
带入上面红色的公式:
宽度:dp = 480 / (240 / 160) = 320dp
高度:dp = 854/ (240 / 160) = 569.3333dp
我做了一个android的demo,一个ImageView宽设置为 320dp 高度为569dp,事实证明,显示的就是全屏幕,也就是以上理论完全正确!
假设有一款手机,屏幕分辨率720px * 1280px 屏幕密度是320。
宽度: dp = 720 / (320 / 160) = 360dp
高度: dp = 大家自己算算看?
也就是说 对于同一张图片,在密度不同的屏幕上,要展示的图片大小px是不同的。如果我们只使用一套图片,则会在不同的屏幕上进行拉伸和缩放。具体图片px和文件夹的关系我会在稍后的博客中写出。
不知道现在 开发者们有没有理解为什么我们写的时候要写成dp呢?
因为写成dp可以自动适应不同屏幕密度的手机,但是dp不是万能的,原因很简单,每个手机的宽度(dp),高度(dp)都不一定是相同的。
简而言之就是说,对于一个宽度为320dp和360dp的两款手机,我们最好的方法就是让布局去自适应,而写死dp的值,可能会导致布局混乱。
这篇文章就写到这里了。如果有时间,我会写写android各种文件夹的原理,关于ldpi,hdpi等这些文件夹的原理。
文章最后附上屏幕密度如何计算。
dpi (屏幕密度)如何计算? 首先,要明白dpi的含义。dpi 指的就是 一英寸屏幕上 到底有多少个像素点。
所以公式为: dpi = 屏幕总px / 屏幕大小。
4.0是屏幕的大小,980是斜线的像素总数,所以我的手机dpi就为240.
以下是Java版的计算Dpi代码
[java] view plaincopy
/**
* E.g: 480*853分辨率,屏幕大小为4.0英寸
* @param width 480
* @param height 853
* @param inch 4.0
* @return dpi
*/
public static double calculateDpi(int width,int height,double inch){
double diagonal = Math.sqrt(width * width + height * height);
return diagonal / inch;
}