本文共 2773 字,大约阅读时间需要 9 分钟。
如果想在不同型号手机对同一个应用做适配,如果你在xml中全部使用dp没有使用px,那么适配上依然很有可能出问题!
无数人存在误区,认为自己使用的都是dp,为什么在手机A上面和手机B上面看上去比例不一样,为什么在A手机上显示正好而手机B上却显示到屏幕外面
每次解释的都很累,所以写此blog
首先先明确几个概念
density值表示每英寸有多少个显示点(*)
dip/dp: device independent pixels(设备独立像素)
注意:dip与屏幕密度有关,屏幕密度与硬件有关,硬件设置不正确,有可能导致dip不能正常显示。在屏幕密度为160的显示屏上,1dip=1px
下面是一些分辨率信息
名称 | 分辨率 | 屏幕密度 |
QVGA | 320*240 | 120 |
WQVGA400 | 400*240 | 120 |
WQVGA432 | 432*240 | 120 |
HVGA | 640*480 | 160 |
WSVGA | 1024*600 | 160 |
WXGA800 | 1280*800 | 160 |
WVGA800 | 800*480 | 240 |
WVGA854 | 854*480 | 240 |
WXGA720 | 1280*720 | 320 |
下面没有特殊说明的话,屏幕的宽度都指其像素数
我们在手机A上面放了一张图片,120px宽,手机屏幕240px宽,也就是说图片的宽度占了整个屏幕的一半
如果把应用安装在手机B上,B的宽度=320px,那么我们希望图片宽度为多少呢?如果大家希望按着比例缩放,那图片宽度应该是160px,占屏幕宽度的50%
如果我们在xml中使用的单位为dp,下面看看如何保持这个比例:
px = (density/160)dp(density这里是(*)的意思)
我们把所期待的比例记为rate,baseDensity=160,屏幕的宽度(像素数)为x,屏幕密度为density
那么rate=((density/baseDensity)*dp)/x;
这里baseDensity是已知的=160,dp也是已知的,因为是你写的嘛。
未知的是density屏幕密度和屏幕宽度x
rate可以写为:
rate=(dp/baseDensity)*(density/x);
现在情况就比较明朗了,rate=K(常数)*(density/x);
如果想保持rate不变,那么需要保证density/x保持比例
给数学不好的同学多解释两句
想保持rate的话,必须要手机A的屏幕密度/屏幕宽度=手机B的屏幕密度/屏幕宽度
或者说手机A的屏幕密度/手机B的屏幕密度=手机A的屏幕宽度/手机B的屏幕宽度
同样,如果你要保持纵向也保持等比缩放,那么也同样需要保持比例。
只有这样,你的应用才能看上去是等比缩放的。
使用dp保持比例只和这些有关,和你屏幕大小半点关系都没有。
还有另一种方式来保持比例:就是直接使用比例方式定义组件大小
但是很有局限性,只有LinearLayout中可以使用android:layout_weight属性
其实很容易理解,给大家举个例子
很多人觉得,如果项目中全部使用dp,那么就可以完美移植。
我们的一个移植项目,任务是把应用从A(分辨率为WXGA720=1280*720)移植到B(分辨率WVGA800=800*480)
其中A的密度=320,B的密度为240
我们现在来看看A横向有多少个dp
A dp数=720/(320/160)=360
B dp数=480/(240/160)=320
手机A横向有360个dp,如果你的图片占用360个dp,B去哪找你多出来的40dp呢!必然它会显示在屏幕外面阿!
ps:下面是一点相关内容
下面是函数void android.util.DisplayMetrics.setToDefaults()
public void setToDefaults() { widthPixels = 0; heightPixels = 0; density = DENSITY_DEVICE / (float) DENSITY_DEFAULT; densityDpi = DENSITY_DEVICE; scaledDensity = density; xdpi = DENSITY_DEVICE; ydpi = DENSITY_DEVICE; noncompatWidthPixels = 0; noncompatHeightPixels = 0;}
其中density变量注释如下
可以看出这个density是个近似值,并不严格按着真实屏幕尺寸计算。
转载地址:http://mycti.baihongyu.com/