之前进行安卓开发的时候遇到一个屏幕适配的问题:Ui给的图片是以iphone6(1920*1080)尺寸做的设计稿,界面是一个弹窗,弹窗背景是一张整图。如果以整图为背景,然后在上面进行控件布局就会出现控件会有偏移的问题。
例如上图里面的用户头像,背景图限定了它的显示位置必须是在小黑框内,如果你设置ImageView的位置不正确的话,就会有偏差导致头像无法正确的先是在背景图限定的小黑框内。但是目前遇到的问题是这样的,我先是在720*1080的手机上适配成功之后,再运行到高分辨率上的手机就会出现头像位置偏移的问题。
那么我们就会产生这样的疑惑:不是说安卓只要是使用dp来设置布局控件的宽、高之后就可以完美进行屏幕适配吗?为什么现在会出现问题呢?
首先我们需要弄清楚几个概念性的东西:
px:像素点。
dp和dip:密度无关像素。开发一般用dp就是可以适配不同密度的手机。
dpi:屏幕像素密度。通过屏幕分辨率除以屏幕尺寸得到的。
屏幕尺寸指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米
比如常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等。
而sp,即scale-independent pixels,与dp类似,但是可以根据文字大小首选项进行放缩,是设置字体大小的御用单位。
然后安卓开发中最主要的屏幕适配其实是对图片的适配,因为一张图片想要正常的展示,就需要把它的宽、高设置为图片的原始宽、高。所以安卓针对图片获取路径对dpi大小范围进行划分。以160dpi为基准,1dp = 1px。为什么要用160为基准呢?上面我们说过,dpi是屏幕像素密度,假如一英寸里面有160个像素,这个屏幕的像素密度就是160dpi,那么在这种情况下,dp和px如何换算呢?在Android中,规定以160dpi为基准,1dip=1px,如果密度是320dpi,则1dip=2px,以此类推。
**安卓按照dpi的大小范围把安卓手机的图片资源包目录分为5个等级,随着手机屏幕的不断更新,我们一般常用的图片资源包路径就是xxhdpi(320dpi-480dpi)、xxxhdpi(480dpi-640dpi)。**也就是说,我们拿到Ui设计稿之后,按照规格下载的2x和3x就可以放入到对应的文件夹下面。
虽然说dp可以去除不同像素密度的问题,使得1dp在不同像素密度上面的显示效果相同,但是还是由于Android屏幕设备的多样性,如果使用dp来作为度量单位,并不是所有的屏幕的宽度都是相同的dp长度。光Google自己一家的产品就已经有这么多的标准,而且屏幕宽度和像素密度没有任何关联关系,即使我们使用dp,在320dp宽度的设备和410dp的设备上,还是会有90dp的差别。当然,我们尽量使用match_parent和wrap_content,尽可能少的用dp来指定控件的具体长宽,再结合上权重,大部分的情况我们都是可以做到适配的。
因为分辨率不一样,所以不能用px;因为屏幕宽度不一样,所以要小心的用dp,那么我们可不可以用另外一种方法来统一单位,不管分辨率是多大,屏幕宽度用一个固定的值的单位来统计呢?
答案是:当然可以。
我们假设手机屏幕的宽度都是320某单位,那么我们将一个屏幕宽度的总像素数平均分成320份,每一份对应具体的像素就可以了。dp能够让同一数值在不同的分辨率展示出大致相同的尺寸大小。但是当设备的尺寸差异较大的时候,就无能为力了。
当然我们还有一个问题,就是为什么安卓以160dpi为基准把图片资源分为5个等级之后,我们的手机分辨率又是怎么样根据自己的像素对应到相同等级hdpi上的呢?
首先,在将对应关系之前,我们一般开发使用的是“蓝湖”来上传我们不同尺寸的图片,我们发现2x和3x的图片尺寸分别对应2倍和3倍的像素值,也就是说,我们手机的实际像素是通过等比缩放宽高得到我们蓝湖上的标准dp值的,这里就是说明了蓝湖的对应规则,就是按像素点把UI稿缩放2~3倍得到的像素,里面的1dp=2px或者3px。
现在你发现了共同点,在安卓标准尺寸基准是160dpi,也就是1dp = 1px,那么320dpi 的含义就是1dp = 2px, 480hdpi的含义就是1dp = 3px。
然后我们在根据标准dpi找到对应的图片资源等级范围,按dpi的范围划分,xxhdpi的图片资源的像素密度范围是320dpi~480dpi,也就是说,我们蓝湖上的1dp = 2px的图片可以放在xhdpi(160dpi ~320dpi)文件夹里面,也可以放在xxhdpi(320dpi ~ 480dpi)文件夹里面;同理,蓝湖1dp = 3px的图片资源可以放在xxhdpi(320dpi ~ 480dpi)或者是放在xxxhdpi(480dpi ~ 640dpi)文件夹下。
但是这个出现了一个临界问题,就是2x和3x的临界存在两个对应的文件夹,我们改怎么选择呢?
通常我们需要UI设计基于1920*1080的设计稿,宽度为360dp,将切图的三倍图放置xxhdpi,如果标注是px,那么我们自动除以3作为dp,如果直接是dp那我们直接拿来使用。
我们发现360hdpi在xxhdpi图片资源文件夹的范围内(320dp ~ 480dp),也就是说蓝湖里面的3倍图对应xxhdpi文件夹,那么我们也就可以推测出:蓝湖的2倍图对应xhdpi图片资源文件夹下(160dpi ~320dpi)。
但是我们的UI团队一般是以iphone6为尺寸标准设计的UI图:如下图:
我们发现iphone6的像素是1286px750px,转成安卓和IOS的对应的单位是除以2,在安卓中375dp对应安卓图片资源的xxhdpi(320dpi ~ 480dpi)这个档位,也就是说就算UI设计团队没有把设计稿以安卓的标准1920 1080为尺寸,但是我们通过把px转成dp 之后就可以找到对应的hdpi图片资源的文件夹。
但是如果提供标准的安卓设备来设计UI设计稿,那么以360为基准,2倍的设计稿就是 1280 * 720,3倍的设计稿应该就是1920 * 1080,设计稿中的3x的图片也就是1080 /3 =360dpi也就是对应我们安卓图片资源的xxhdpi(320dpi ~ 480dpi)范围。 我们很容易犯以错误,就是容易理解我们手机的hdpi是可以根据手机宽度的像素点除以2或者3得到,这是一个假象!!!
我们的手机hdpi其实是需要我们手机对角线的px除以手机的对角线的长度得到的,也即是说每个手机的hdpi是固定的一个数值,而我们只能通过hdpi来对应手机的像素来找到图片的放置位置。
安卓屏幕分辨率划分
安卓屏幕适配方案
蓝湖安卓和IOS对应尺寸说明文档
iphone6的切图如何适配Android?
安卓ScreenMatch适配方式。