最近看了一篇今日头条的适配方案https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA
开始看的地址不是这里,其他地址 ,讲的很模糊(估计是理解年龄大了,理解能力差了)。里面有些dp,px, dpi相关的东西看了很久没理解。应该 是说其中的换算搞了很久没懂,所以说一篇好的博文事办功倍,差的事倍功半。
其实今日头条的适配方案和dp ,px 没啥直接联系 ,主要是作为Android开发以前对这块也不是很在意,导致后面看的时候没底。废话不多说了,直接来吧 。
px :表示像素点 ,1px 表示手机屏幕上的一个点 。像我们手机720px*1280px, 简单理解就是在手机宽上有720个点,在手机高上面1280个点,这些px不是指手机的尺寸 ,是指像素而已,简单理解就是点。
尺寸: 手机的对角线长度(拿个尺子量就行了)。这个才是只手机的大小(以前迷迷糊糊的,以为尺寸是指 px)。
dp:主要是这个 ,很多做Android开发的,估计很熟练是什么,也很熟练使用,但是不知道是什么。其实很简单容易理解就是Android中的长度单位。就像我们生活中的尺子有厘米毫米啥的 ,没那么多玄乎解释,Android中的长度单位就是dp。其他不用管什么专业名词(我前面被唬了好久,什么没每平方英寸的像素,好像是对的,其实不用管那么多,理解为Android 的长度单位就行了)。至于为什么有dp,不使用统一的px,这还要讨论另一个话题手机密度(Density)。我们知道Android手机下面有几个存放文件图片的文件夹。
这是出现dp的原因,不同文件夹下的手机密度不同,具体的ldpi目录下density为0.75,mdpi目录下density为1,hdpi为density1.5
xhdpi为density2, xxxhdpi的densty为3。
density:手机密度 。density = dpi/160;估计很多人看到这个160都不知道为啥,其实是一个基准(就是一个标准),
原因有2 ,
第一是google官方第一款Android手机(HTC的T-Mobile G1)的dpi就是160。
第二种解释就是Android主流的dpi有120,160,240,320,480。在160dpi的情况下 1dp = 1px,在120dpi的情况下 0.75 dp = 1px,在240dpi的情况下 1.5 dp = 1px,在320dpi的情况下 2 dp = 1px,在480dpi的情况下 3 dp = 1px,这样计算出来的数字在不同手机密度下的是最简单的,简单的说就是为了不同手机手机密度的屏幕进行适配 。 如果你以120dpi为标准 ,发现在160dpi下为1.3333,其他类似存在误差,所以标准是160.
dpi:dpi = √(px^2*py^2)/ 手机尺寸 (手机对角线的长度),每英寸的手机像素,px表示宽上的像素,py表示手机高上的像素。简单点说就是手机对角线上的像素/对角线的长度。例如手机是1920*1080 ,实际宽度是2000,手机5寸那么dpi = √(1920^2+1080^2)/5 = 440。
看今日头条的文章的时候 ,还有个不理解的地方是px = dp*density,好吧,这个地方其实理解不理解都无所谓,但是开发的话,能多理解点东西都是好的,假如现在有一个手机屏幕宽度为200px,假如现在有个长度有100dp的view要显示, 这么说还有点复杂,简单点,假如现在有1个100dp的图片,放在ldpi下显示的长度是px = 100*0.75 就是75px,放在mdpi下就是px= 100*1 就是100px,显然这张图片放在ldpi下和放在mdpix下占用的屏幕比例不同。这就是dp出现的原因。
事实上上面所有的对于今日头条的适配没有多大的理解。今日头条的适配其实可以用简单例子说面。
假定UI设计师问你的适配方案,你让UI按照宽度为300dp的设计就行了。(为啥300dp,其实你可以改为其他数字 120dp, 200dp都行,只是一个举例),现在UI图中有一个ImageView为100dp宽度的需要画出来。
现在还假如你有2台手机 ,手机的宽度相同,都是400px(随便取得数字,为什么手机宽度是px,可以通过"context.getResource().getDisplayMetrics().widthPixels"),a手机的density为1,b手机的density为2(每台手机的density是固定的,可以通过“context.getResource().getDisplayMetrics().density”获取),
根据公式 px = density* dp ,在a手机上 ivWidth= 1*100dp =100px,那么imageview在屏幕中宽度占比是100px/400px =0.25.
在b手机上 ivWidth = 2*100dp = 200px,这个imageview在屏幕中的占比为 200px/400px = 0.5.
完全不符合适配的要求吧,一个是占屏幕的1/4,一个占1/2, 还有些可能显示imageview显示不完。正常的应该是在设计图中占用1/4 ,那么在其他手机上应该都是1/4是吧。所以今日头条的解决方案出现了,修改手机的density。手机的density =imageview的宽度/设计图的宽度= 100dp/300dp =1/3,
那么在手机a上 ivwidth= 手机宽度*density = 400dp*(1/3) = 133.33px 占用的屏幕的比例是 133px/400p x =1/3。
在b手机上 ivwidth= 手机宽度*density = 400dp*3 =133.33px 占用的屏幕的比利时133px/400px =1/3。
这样看的话在a,b俩款手机上没有差别。
根据公式 ivwidth = density *dp = (view的宽度/设计图的总宽度)*屏幕的宽度 。说来说去 其实就是和你设计图的比例有关了,和手机手机密度(density)没有关系了。
使用过程中需要注意一点是,在用第三方库的时候 ,如果有图片的话,会有问提,因为UI给的设计图,和第三方库的宽的基准可能不同。需要提前规避,要么让UI设计师采用第三方库的UI标准,要么将UI库导出来,重新设计相关的UI。