为什么要适配?
Android系统的开放性导致的屏幕尺寸碎片化,出现同一元素在不同手机上显示不同的问题。试想一下这么一个场景: 为4.3寸屏幕准备的UI设计图,运行在5.0寸的屏幕上,很可能在右侧和下侧存在大量的空白;而5.0寸的UI设计图运行到4.3寸的设备上,很可能显示不下。为了保证用户获得一致的用户体验效果,使得某一元素在Android不同尺寸、不同分辨率的、不同系统的手机上具备相同的显示效果,能够保持界面上的效果一致,我们需要对各种手机屏幕进行适配!
基本概念
-
像素(px):
-
含义:通常所说的像素,就是CCD/CMOS上光电感应元件的数量,一个感光元件经过感光,光电信号转换,A/D转换等步骤以后,在输出的照片上就形成一个点,我们如果把影像放大数倍,会发现这些连续色调其实是由许多色彩相近的小方点所组成,这些小方点就是构成影像的最小单位“像素”(Pixel)。简而言之,像素就是手机屏幕的最小构成单元。
- 单位:px(pixel),1px = 1像素点 一般情况下UI设计师的设计图会以px作为统一的计量单位
- 分辨率:
- 含义:手机在横向、纵向上的像素点数总和 一般描述成 宽*高 ,即横向像素点个数 * 纵向像素点个数(如1080 x 1920)。
- 单位:px(pixel),1px = 1像素点
- 屏幕尺寸(in):
- 含义:手机对角线的物理尺寸
- 单位 英寸(inch),一英寸大约2.54cm 常见的尺寸有4.7寸、5寸、5.5寸、6寸
-
屏幕像素密度(dpi):
-
含义:每英寸的像素点数。 例如每英寸内有160个像素点,则其像素密度为160dpi。
- 单位:dpi(dots per inch)
- 计算公式: 像素密度 = 像素 / 尺寸 (dpi = px / in) 标准屏幕像素密度(mdpi): 每英寸长度上还有160个像素点(160dpi),即称为标准屏幕像素密度(mdpi)。
密度类型 | 代表的分辨率(px) | 屏幕像素密度(dpi) |
---|---|---|
低密度(idpi) | 240x320 | 120 |
中密度(mdpi) | 320x480 | 160 |
高密度(hdpi) | 480x800 | 240 |
超密度(hdpi) | 720x1280 | 320 |
超超密度(hdpi) | 1080x1920 | 480 |
屏幕尺寸、分辨率、像素密度三者关系
一部手机的分辨率是宽x高,屏幕大小是以寸为单位,那么三者的关系是:
5. 密度无关像素(dp):
- 含义:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关
- 单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果,是安卓特有的长度单位。 场景例子:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。
-
dp与px的转换:1dp = (dpi / 160 ) * 1px;
-
独立比例像素(sp):
-
含义:scale-independent pixel,叫sp或sip
-
单位:sp,字体大小专用单位 Android开发时用此单位设置文字大小,可根据字体大小首选项进行缩放; 推荐使用12sp、14sp、18sp、22sp作为字体大小,不推荐使用奇数和小数,容易造成精度丢失,12sp以下字体太小。
-
sp 与 dp 的区别:
dp只跟屏幕的像素密度有关; sp和dp很类似但唯一的区别是,Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),当文字尺寸是“正常”时1sp=1dp=0.00625英寸,而当文字尺寸是“大”或“超大”时,1sp>1dp=0.00625英寸。类似我们在windows里调整字体尺寸以后的效果——窗口大小不变,只有文字大小改变。
适配方案
将分为布局组件、布局、图片、代码、接口等几方面来谈。
关于布局组件的适配
- 使用dp或者sp代替px
- 使用约束布局/相对布局代替绝对布局
- 使用wrap_content,match-parent,权重替代具体的尺寸
- 使用minwidth,minheight,等属性
- dimens使用
关于布局的适配
- 使用large限定符
同时适配手机和平板/电视,布局名称中使用large限定符,系统回在较大(7英寸或者更大)屏幕上自动选择此布局。
- 最小宽度限定符
使用Size限定符有一个问题会让很多程序员感到头疼,large到底是指多大呢?很多应用程序都希望能够更自由地为不同屏幕设备加载不同的布局,不管它们是不是被系统认定为”large”。这就是Android为什么在3.2以后引入了”Smallest-width”限定符。
最小宽度限定符可让您通过指定某个最小宽度(以 dp 为单位)来定位屏幕。例如,标准 7 英寸平板电脑的最小宽度为 600 dp,因此如果您要在此类屏幕上的用户界面中使用双面板(但在较小的屏幕上只显示列表),您可以使用上文中所述的单面板和双面板这两种布局,但您应使用 sw600dp 指明双面板布局仅适用于最小宽度为 600 dp 的屏幕,而不是使用 large 尺寸限定符。
也就是说,对于最小宽度大于等于 600 dp 的设备,系统会选择 layout-sw600dp/main.xml(双面板)布局,否则系统就会选择 layout/main.xml(单面板)布局。
但 Android 版本低于 3.2 的设备不支持此技术,原因是这些设备无法将 sw600dp 识别为尺寸限定符,因此我们仍需使用 large 限定符。这样一来,就会有一个名称为 res/layout-large/main.xml 的文件(与 res/layout-sw600dp/main.xml 一样)。但是没有太大关系,我们将马上学习如何避免此类布局文件出现的重复。
避免布局文件重复可以使用布局别名 3. 使用屏幕方向限定符 4.
图片适配
- logo图标建议按照官方标准准备好图标
屏幕密度 | 对应图片大小(px) | 图片资源目录 |
---|---|---|
120dip(idpi) | 36x36 | mipmap-idpi |
160dip(mdpi) | 48x48 | mipmap或者mipmap-mdpi |
240dip(hdpi) | 72x72 | mipmap-hdpi |
320dip(xhdpi) | 96x96 | mipmap-xhdpi |
480dip(xxhdpi) | 144x144 | mipmap-xxhdpi |
640dip(xxxhdpi) | 192x192 | mipmap-xxxhdpi |
- 普通图片和图标
建议按照官方的密度类型进行切图即可,但一般我们只需xxhdpi或xxxhdpi的切图即可满足我们的需求; - 自动拉伸图.9图片类型(按钮)
- 动画、自定义view、shape
- imageView的scaleType适配
1. android:scaleType=“center”
保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size时,多出来的部分被截掉。
2. android:scaleType=“center_inside”
以原图正常显示为目的,如果原图大小大于ImageView的size,就按照比例缩小原图的宽高,居中显示在ImageView中。如果原图size小于ImageView的size,则不做处理居中显示图片。
3. android:scaleType=“center_crop”
以原图填满ImageView为目的,如果原图size大于ImageView的size,则与center_inside一样,按比例缩小,居中显示在ImageView上。如果原图size小于ImageView的size,则按比例拉升原图的宽和高,填充ImageView居中显示。
4. android:scaleType=“matrix”
不改变原图的大小,从ImageView的左上角开始绘制,超出部分做剪切处理。
5. androd:scaleType=“fit_xy”
把图片按照指定的大小在ImageView中显示,拉伸显示图片,不保持原比例,填满ImageView.
6. android:scaleType=“fit_start”
把原图按照比例放大缩小到ImageView的高度,显示在ImageView的start(前部/上部)。
7. android:sacleType=“fit_center”
把原图按照比例放大缩小到ImageView的高度,显示在ImageView的center(中部/居中显示)。
8. android:scaleType=“fit_end”
把原图按照比例放大缩小到ImageView的高度,显示在ImageVIew的end(后部/尾部/底部)
- 代码适配
通过api测量手机屏幕宽高度,然后根据需求来设置
- 接口适配
本地加载图片前判断手机分辨率或者像素密度,向服务器请求对应级别图片