UI适配
屏幕尺寸
含义:手机对角线的物理尺寸
单位:英寸(inch),1英寸=2.54cm
Android手机常见的尺寸有5寸、5.5寸、6寸等等
屏幕分辨率
含义:手机在横向、纵向上的像素点数总和
一般描述成屏幕的"宽x高”=AxB
含义:屏幕在横向方向(宽度)上有A个像素点,在纵向方向
(高)有B个像素点
例子:1080x1920,即宽度方向上有1080个像素点,在高度方向上有1920个像素点
单位:px(pixel),1px=1像素点
UI设计师的设计图会以px作为统一的计量单位
Android手机常见的分辨率:320x480、480x800、720x1280、1080x1920
屏幕像素密度
含义:每英寸的像素点数
单位:dpi(dots per ich)
假设设备内每英寸有160个像素,那么该设备的屏幕像素密度=160dpi
安卓手机对于每类手机屏幕大小都有一个相应的屏幕像素密度:
密度类型
代表的分辨率(px)
屏幕像素密度(dpi)
低密度(ldpi)
240x320
120
中密度(mdpi)
320x480
160
高密度(hdpi)
480x800
240
超高密度(xhdpi)
720x1280
320
超超高密度(xxhdpi)
1080x1920
480
屏幕尺寸、分辨率、像素密度三者关系
一部手机的分辨率是宽x高,屏幕大小是以寸为单位,那么三者的关系是:
三者关系示意图
密度无关像素
含义:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关。
单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果
Android开发时用dp而不是px单位设置图片大小,是Android特有的单位
场景:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。
dp与px的转换
因为ui设计师给你的设计图是以px为单位的,Android开发则是使用dp作为单位的,那么我们需要进行转换:
密度类型
代表的分辨率(px)
屏幕密度(dpi)
换算(px/dp)
比例
低密度(ldpi)
240x320
120
1dp=0.75px
3
中密度(mdpi)
320x480
160
1dp=1px
4
高密度(hdpi)
480x800
240
1dp=1.5px
6
超高密度(xhdpi)
720x1280
320
1dp=2px
8
超超高密度(xxhdpi)
1080x1920
480
1dp=3px
12
在Android中,规定以160dpi(即屏幕分辨率为320x480)为基准:1dp=1px
独立比例像素
含义:scale-independent pixel,叫sp或sip
单位:sp
Android开发时用此单位设置文字大小,可根据字体大小首选项进行缩放
推荐使用12sp、14sp、18sp、22sp作为字体设置的大小,不推荐使用奇数和小数,容易造成精度的丢失问题;小于12sp的字体会太小导致用户看不清
为什么要进行Android屏幕适配
由于Android系统的开放性,任何用户、开发者、OEM厂商、运营商都可以对Android进行定制,于是导致:
Android系统碎片化:小米定制的MIUI、魅族定制的flyme、华为定制的EMUI等等
当然都是基于Google原生系统定制的
Android机型屏幕尺寸碎片化:5寸、5.5寸、6寸等等
Android屏幕分辨率碎片化:320x480、480x800、720x1280、1080x1920
据友盟指数显示,统计至2015年12月,支持Android的设备共有27796种
当Android系统、屏幕尺寸、屏幕密度出现碎片化的时候,就很容易出现同一元素在不同手机上显示不同的问题。
试想一下这么一个场景: 为4.3寸屏幕准备的UI设计图,运行在5.0寸的屏幕上,很可能在右侧和下侧存在大量的空白;而5.0寸的UI设计图运行到4.3寸的设备上,很可能显示不下。
为了保证用户获得一致的用户体验效果:
使得某一元素在Android不同尺寸、不同分辨率的手机上具备相同的显示效果
于是,我们便需要对Android屏幕进行适配。
屏幕适配问题的本质
使得“布局”、“布局组件”、“图片资源”、“用户界面流程”匹配不同的屏幕尺寸
使得布局、布局组件自适应屏幕尺寸; 根据屏幕的配置来加载相应的UI布局、用户界面流程
使得“图片资源”匹配不同的屏幕密度
适配类型和手段
布局适配
使用布局match_parent, wrap_content进行部分基本宽高适配
使用RelativeLayout相对定位
使用LinearLayout和ConstraintLayout进行布局宽高比适配,通过宽高比适配不同手机
图片适配
图片进行自适应宽高拉伸
提供不同尺寸手机的图片
.9.png 自动拉伸图片
尺寸适配
密度适配 layout-hdpi values-hdpi等
宽高限定适配 layout-1920x1080 values-1920x1080等
最小宽度适配 layout-sw360dp values-sw360dp
适配方案
dp适配
通过dp加上自适应布局和weight比例布局可以基本解决不同手机上适配的问题,这基本是最原始的Android适配方案。
这种方式存在两个小问题,第一,这只能保证我们写出来的界面适配绝大部分手机,部分手机仍然需要单独适配,为什么dp只解决了90%的适配问题,因为并不是所有的1080P的手机dpi都是480,比如Google 的Pixel2(19201080)的dpi是420,也就是说,在Pixel2中,1dp=2.625px,这样会导致相同分辨率的手机中,这样,一个100dp100dp的控件,在一般的1080P手机上,可能都是300px,而Pixel 2 中 ,就只有262.5px,这样控件的实际大小会有所不同。
为了更形象的展示,假设我们在布局文件中把一个ImageView的宽度设置为360dp,那么在下面两张图中表现是不一样的:
图一是1080P,480dpi的手机,图二是1080P,420dpi的手机
从上面的布局中可以看到,同样是1080P的手机,差异是比较明显的。在这种情况下,我们的UI可能需要做一些微调甚至单独适配。
第二个问题,这种方式无法快速高效的把设计师的设计稿实现到布局代码中,通过dp直接适配,我们只能让UI基本适配不同的手机,但是在设计图和UI代码之间的鸿沟,dp是无法解决的,因为dp不是真实像素。而且,设计稿的宽高往往和Android的手机真实宽高差别极大,以我们的设计稿为例,设计稿的宽高是375px750px,而真实手机可能普遍是10801920,
那么在日常开发中我们是怎么跨过这个鸿沟的呢?基本都是通过百分比啊,或者通过估算,或者设定一个规范值等等。总之,当我们拿到设计稿的时候,设计稿的ImageView是128px128px,当我们在编写layout文件的时候,却不能直接写成128dp128dp。在把设计稿向UI代码转换的过程中,我们需要耗费相当的精力去转换尺寸,这会极大的降低我们的生产力,拉低开发效率。
宽高限定符适配
宽高限定符适配,简单说,就是穷举市面上所有的Android手机的宽高像素值:values-480x320等
如果我们的UI设计界面使用的就是基准分辨率,那么我们就可以按照设计稿上的尺寸填写相对应的dimens引用了,而当APP运行在不同分辨率的手机中时,这些系统会根据这些dimens引用去该分辨率的文件夹下面寻找对应的值。这样基本解决了我们的适配问题,而且极大的提升了我们UI开发的效率,
但是这个方案有一个致命的缺陷,那就是需要精准命中才能适配,比如1920x1080的手机就一定要找到1920x1080的限定符,否则就只能用统一的默认的dimens文件了。而使用默认的尺寸的话,UI就很可能变形,简单说,就是容错机制很差。
smallestWidth适配(最小宽度适配)
smallestWidth适配,或者叫sw限定符适配。指的是Android会识别屏幕可用高度和宽度的最小尺寸的dp值(其实就是手机的宽度值),然后根据识别到的结果去资源文件中寻找对应限定符的文件夹下的资源文件。
这种机制和上文提到的宽高限定符适配原理上是一样的,都是系统通过特定的规则来选择对应的文件。
举个例子,小米5的dpi是480,横向像素是1080px,根据px=dp(dpi/160),横向的dp值是1080/(480/160),也就是360dp,系统就会去寻找是否存在value-sw360dp的文件夹以及对应的资源文件。
smallestWidth限定符适配和宽高限定符适配最大的区别在于,前者有很好的容错机制,如果没有value-sw360dp文件夹,系统会向下寻找,比如离360dp最近的只有value-sw350dp,那么Android就会选择value-sw350dp文件夹下面的资源文件。这个特性就完美的解决了上文提到的宽高限定符的容错问题。
这套方案是上述几种方案中最接近完美的方案。 首先,从开发效率上,它不逊色于上述任意一种方案。根据固定的放缩比例,我们基本可以按照UI设计的尺寸不假思索的填写对应的dimens引用。 我们还有以375个像素宽度的设计稿为例,在values-sw360dp文件夹下的diemns文件应该怎么编写呢?这个文件夹下,意味着手机的最小宽度的dp值是360,我们把360dp等分成375等份,每一个设计稿中的像素,大概代表smallestWidth值为360dp的手机中的0.96dp,那么接下来的事情就很简单了,假如设计稿上出现了一个10px*10px的ImageView,那么,我们就可以不假思索的在layout文件中写下对应的尺寸。
而这种diemns引用,在不同的values-swdp文件夹下的数值是不同的,比如values-sw360dp和values-sw400dp,
当系统识别到手机的smallestWidth值时,就会自动去寻找和目标数据最近的资源文件的尺寸。
其次,从稳定性上,它也优于上述方案。原生的dp适配可能会碰到Pixel 2这种有些特别的手机需要单独适配,但是在smallestWidth适配中,通过计算Pixel 2手机的的smallestWidth的值是411,我们只需要生成一个values-sw411dp(或者取整生成values-sw410dp也没问题)就能解决问题。
smallestWidth的适配机制由系统保证,我们只需要针对这套规则生成对应的资源文件即可,不会出现什么难以解决的问题,也根本不会影响我们的业务逻辑代码,而且只要我们生成的资源文件分布合理,,即使对应的smallestWidth值没有找到完全对应的资源文件,它也能向下兼容,寻找最接近的资源文件。
UI适配框架
参考内容
Last updated
Was this helpful?