为什么要适配?

Android系统的开放性导致的屏幕尺寸碎片化,出现同一元素在不同手机上显示不同的问题。试想一下这么一个场景: 为4.3寸屏幕准备的UI设计图,运行在5.0寸的屏幕上,很可能在右侧和下侧存在大量的空白;而5.0寸的UI设计图运行到4.3寸的设备上,很可能显示不下。为了保证用户获得一致的用户体验效果,使得某一元素在Android不同尺寸、不同分辨率的、不同系统的手机上具备相同的显示效果,能够保持界面上的效果一致,我们需要对各种手机屏幕进行适配!

基本概念

  1. 像素(px):

  2. 含义:通常所说的像素,就是CCD/CMOS上光电感应元件的数量,一个感光元件经过感光,光电信号转换,A/D转换等步骤以后,在输出的照片上就形成一个点,我们如果把影像放大数倍,会发现这些连续色调其实是由许多色彩相近的小方点所组成,这些小方点就是构成影像的最小单位“像素”(Pixel)。简而言之,像素就是手机屏幕的最小构成单元。

  3. 单位:px(pixel),1px = 1像素点 一般情况下UI设计师的设计图会以px作为统一的计量单位
  4. 分辨率:
  5. 含义:手机在横向、纵向上的像素点数总和 一般描述成 宽*高 ,即横向像素点个数 * 纵向像素点个数(如1080 x 1920)。
  6. 单位:px(pixel),1px = 1像素点
  7. 屏幕尺寸(in):
  8. 含义:手机对角线的物理尺寸
  9. 单位 英寸(inch),一英寸大约2.54cm 常见的尺寸有4.7寸、5寸、5.5寸、6寸
  10. 屏幕像素密度(dpi):

  11. 含义:每英寸的像素点数。 例如每英寸内有160个像素点,则其像素密度为160dpi。

  12. 单位:dpi(dots per inch)
  13. 计算公式: 像素密度 = 像素 / 尺寸 (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高,屏幕大小是以寸为单位,那么三者的关系是: dpipxinch.png 5. 密度无关像素(dp):

  • 含义:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关
  • 单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果,是安卓特有的长度单位。 场景例子:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。
  • dp与px的转换:1dp = (dpi / 160 ) * 1px; dptopx.png

  • 独立比例像素(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里调整字体尺寸以后的效果——窗口大小不变,只有文字大小改变。

适配方案

将分为布局组件、布局、图片、代码、接口等几方面来谈。

关于布局组件的适配
  1. 使用dp或者sp代替px
  2. 使用约束布局/相对布局代替绝对布局
  3. 使用wrap_content,match-parent,权重替代具体的尺寸
  4. 使用minwidth,minheight,等属性
  5. dimens使用
关于布局的适配
  1. 使用large限定符
同时适配手机和平板/电视,布局名称中使用large限定符,系统回在较大(7英寸或者更大)屏幕上自动选择此布局。
  1. 最小宽度限定符
使用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.

图片适配
  1. 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
  1. 普通图片和图标
    建议按照官方的密度类型进行切图即可,但一般我们只需xxhdpi或xxxhdpi的切图即可满足我们的需求;
  2. 自动拉伸图.9图片类型(按钮)
  3. 动画、自定义view、shape
  4. 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(后部/尾部/底部)

  1. 代码适配
通过api测量手机屏幕宽高度,然后根据需求来设置
  1. 接口适配
本地加载图片前判断手机分辨率或者像素密度,向服务器请求对应级别图片