Android屏幕适配

Android机型众多

Posted by wushiqian on August 28, 2019

屏幕适配

为什么要适配

​ 由于Android系统的开放性,任何用户、开发者、硬件厂商、运营商都可以对Android系统和硬件进行定制,修改成他们想要的样子。 那么这种“碎片化”到达什么程度呢?

  • Android系统碎片化:基于Google原生系统,小米定制的MIUI、魅族定制的flyme、华为定制的EMUI等等;

  • Android机型屏幕尺寸碎片化:5寸、5.5寸、6寸等等;

  • Android屏幕分辨率碎片化:320x480、480x800、720x1280、1080x1920等;

基本概念

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

单位:px(pixel),1px = 1像素点 一般情况下UI设计师的设计图会以px作为统一的计量单位。

2、分辨率: 含义:手机在横向、纵向上的像素点数总和 一般描述成 宽*高 ,即横向像素点个数 * 纵向像素点个数(如1080 x 1920)。

单位:px(pixel),1px = 1像素点

3、屏幕尺寸(in): 含义:手机对角线的物理尺寸

单位 英寸(inch),一英寸大约2.54cm 常见的尺寸有4.7寸、5寸、5.5寸、6寸

4、屏幕像素密度(dpi): 含义:每英寸的像素点数。 例如每英寸内有160个像素点,则其像素密度为160dpi。

单位:dpi(dots per inch)

计算公式: 像素密度 = 像素 / 尺寸 (dpi = px / in)

标准屏幕像素密度(mdpi): 每英寸长度上还有160个像素点(160dpi),即称为标准屏幕像素密度(mdpi)。

屏幕尺寸、分辨率、像素密度三者关系 一部手机的分辨率是宽x高,屏幕大小是以寸为单位,那么三者的关系是:

假设一部手机的分辨率是1080x1920(px),屏幕大小是5寸

5、密度无关像素(dp): 含义:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关

单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果,是安卓特有的长度单位。

场景例子:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。

dp与px的转换:1dp = (dpi / 160 ) * 1px;

6、独立比例像素(sp): 含义:scale-independent pixel,叫sp或sip

单位:sp,字体大小专用单位 Android开发时用此单位设置文字大小,可根据字体大小首选项进行缩放; 推荐使用12sp、14sp、18sp、22sp作为字体大小,不推荐使用奇数和小数,容易造成精度丢失,12sp以下字体太小。

7、sp 与 dp 的区别:

​ dp只跟屏幕的像素密度有关;

​ sp和dp很类似但唯一的区别是,Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),当文字尺寸是“正常”时1sp=1dp=0.00625英寸,而当文字尺寸是“大”或“超大”时,1sp>1dp=0.00625英寸。类似我们在windows里调整字体尺寸以后的效果——窗口大小不变,只有文字大小改变。

​ 追到android源码,发现系统内部用applyDimension() (路径:android.util.TypedValue.applyDimension())将所有单位都转换成px 再处理:

关于布局组件的适配

使用密度无关像素指定尺寸

使用相对布局或线性布局,不要使用绝对布局

使用wrap_content、match_parent、权重

使用minWidth、minHeight、lines等属性

dimens使用

关于布局的适配

使用Size限定符

最小宽度限定符

使用布局别名

使用屏幕方向限定符

多套layout适配

关于图片的适配

LOGO 图标

普通图片和图标

建议安装官方的密度类型进行切图即可,但一般我们只需xxhdpi或xxxhdpi的切图即可满足我们的需求;

自动拉伸位图:Nine-Patch的图片类型

动画、自定义view、shape

ImageView的ScaleType适配

  • android:scaleType=“center” 保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size时,多出来的部分被截掉。

  • android:scaleType=“center_inside” 以原图正常显示为目的,如果原图大小大于ImageView的size,就按照比例缩小原图的宽高,居中显示在ImageView中。如果原图size小于ImageView的size,则不做处理居中显示图片。

  • android:scaleType=“center_crop” 以原图填满ImageView为目的,如果原图size大于ImageView的size,则与center_inside一样,按比例缩小,居中显示在ImageView上。如果原图size小于ImageView的size,则按比例拉升原图的宽和高,填充ImageView居中显示。

  • android:scaleType=“matrix” 不改变原图的大小,从ImageView的左上角开始绘制,超出部分做剪切处理。

  • androd:scaleType=“fit_xy” 把图片按照指定的大小在ImageView中显示,拉伸显示图片,不保持原比例,填满ImageView.

  • android:scaleType=“fit_start” 把原图按照比例放大缩小到ImageView的高度,显示在ImageView的start(前部/上部)。

  • android:sacleType=“fit_center” 把原图按照比例放大缩小到ImageView的高度,显示在ImageView的center(中部/居中显示)。

  • android:scaleType=“fit_end” 把原图按照比例放大缩小到ImageView的高度,显示在ImageVIew的end(后部/尾部/底部)

适配方案

刘海屏适配

  • Android P 刘海屏适配方案

​ Android P 支持最新的全面屏以及为摄像头和扬声器预留空间的凹口屏幕。通过全新的 DisplayCutout 类,可以确定非功能区域的位置和形状,这些区域不应显示内容。要确定这些凹口屏幕区域是否存在及其位置,使用 getDisplayCutout() 函数。

DisplayCutout 类方法 说明
getBoundingRects() 返回Rects的列表,每个Rects都是显示屏上非功能区域的边界矩形
getSafeInsetLeft () 返回安全区域距离屏幕左边的距离,单位是px
getSafeInsetRight () 返回安全区域距离屏幕右边的距离,单位是px
getSafeInsetTop () 返回安全区域距离屏幕顶部的距离,单位是px
getSafeInsetBottom() 返回安全区域距离屏幕底部的距离,单位是px

Android P 中 WindowManager.LayoutParams 新增了一个布局参数属性 layoutInDisplayCutoutMode:

模式 模式说明
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 只有当DisplayCutout完全包含在系统栏中时,才允许窗口延伸到DisplayCutout区域。 否则,窗口布局不与DisplayCutout区域重叠。
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 该窗口决不允许与DisplayCutout区域重叠。
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 该窗口始终允许延伸到屏幕短边上的DisplayCutout区域。

今日头条适配方案

一种极低成本的Android屏幕适配方式

smallestWidth 限定符适配方案

smallestWidth 限定符适配方案

​ smallestWidth适配,或者叫sw限定符适配。指的是Android会识别屏幕可用高度和宽度的最小尺寸的dp值(其实就是手机的宽度值),然后根据识别到的结果去资源文件中寻找对应限定符的文件夹下的资源文件。

AndroidAutoSize

骚年你的屏幕适配方式该升级了!(一)-今日头条适配方案 骚年你的屏幕适配方式该升级了!(二)-SmallestWidth 限定符适配方案 今日头条屏幕适配方案终极版正式发布!