gagapencil学习小站

屏幕适配

字数统计: 2.4k阅读时长: 8 min
2019/06/20 Share

1.基本概念

1.1 px

简单说,像素就是表示一个点的RGB颜色;这个点,是数学上的概念,是没有大小的;但是屏幕显示一个像素是需要大小的,具体大小是屏幕尺寸除以屏幕分辨率

1.2 屏幕分辨率

屏幕分辨率就是屏幕最多能显示多少个像素,如果屏幕最多能显示1080 * 1920个像素,屏幕大小是3 * 5英寸的,那么每个像素占用(3/1080) * (5/1920)的大小。一般情况下屏幕宽高比和像素宽高比是相等的,

1.2 ppi, dpi

屏幕上每英寸上点的数量,我们叫做DPI(dots per inch),因为屏幕上面每个点对应一个像素,所以也有叫PPI;两者大部分情况可以混用,有时候又不一样。当DPI小的时候,每个点的物理尺寸就变大(点的大小理解为 DPI 分之一 英寸;比如DPI是160,每个点就是 1/160 英寸);所以要解决屏幕颗粒大的问题,提高DPI值就可以了。但DPI提高后,又出现了另外一个问题:同样像素的Bitmap在新的屏幕上看起来小了。假设把DPI从160提高到320,原来160像素在新屏幕上的大小只有原来的一半。

1.3 dp,sp

  • 因为在不同dpi下,相同像素下长度不一样,android引入了dp(density independent pixel),sp(Scale-independent Pixel)作为长度单位。简单粗暴直接规定一英寸就是160dp,即1dp=1/160inch;android内部帮我们做了1dp对应多少像素的换算,即(px=dp*(dpi/160)),即1dp在dpi为160的设备上对应1px,在320dpi上对应2px。如此保证在相同dp下,在不同屏幕密度下显示一样的长度。
  • sp和dp很类似但唯一的区别是,Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),当文字尺寸是“正常”时,1sp=1dp=1/160inch,而当文字尺寸是“大”或“超大”时,1sp=1sp*scale>1/160inch。类似我们在windows里调整字体尺寸以后的效果——窗口大小不变,只有文字大小改变。

    1.3.1 dp的缺陷

  • dp解决了大小一致的问题,没解决比列的问题;如果我们设定控件的宽是160dp,在宽是3inch的屏幕上占比是1/3,在宽是4inch的屏幕上占比是1/4。
  • 不精确;android会将实际dpi进行修正 然后根据density=dpi/160算出density,而px=density * dp;由此可知不是精确的,因为会修正。如实际屏幕密度为321dpi,参考下表知修正后的dpi为480,density为3。
    名称 代表分辨率 范围 修正 density
    mdpi 320x480 120dpi~160dpi 160dpi 1
    hdpi 480x800 160dpi~240dpi 240dpi 1.5
    xhdpi 720x1280 240dpi~320dpi 320dpi 2
    xxhdpi 1080x1920 320dpi~480dpi 480dpi 3
    xxxhdpi 480dpi~640dpi 640dp 4
  • 和美工的设计搞不对应。如设计师的图片基准是1080 * 1920,单位是px,如果图标是60px*60px,我们不能直接写60dp * 60dp,要根据屏幕密度换算成相应的dp。

    2.宽高限定符适配

    2.1好处

    宽高限定符解决了比列,不精确和 美工设计稿不对应三大问题。

    2.2使用

    做法就是穷举市面上所有的Android手机的宽高像素值:
    image.png

设定一个基准的分辨率,其他分辨率都根据这个基准分辨率来计算,在不同的尺寸文件夹内部,根据该尺寸编写对应的dimens文件。
比如以480x320为基准分辨率

宽度为320,将任何分辨率的宽度整分为320份,取值为x1-x320
高度为480,将任何分辨率的高度整分为480份,取值为y1-y480

那么对于800480的分辨率的dimens文件来说,
x1=(480/320)
1=1.5px
x2=(480/320)*2=3px
image.png
这个时候,如果我们的UI设计界面使用的就是基准分辨率,那么我们就可以按照设计稿上的尺寸填写相对应的dimens引用了,而当APP运行在不同分辨率的手机中时,这些系统会根据这些dimens引用去该分辨率的文件夹下面寻找对应的值。这样基本解决了我们的适配问题,而且极大的提升了我们UI开发的效率,

2.3缺陷

  • 需要精准命中才能适配,比如1920x1080的手机就一定要找到1920x1080的限定符,否则就只能用统一的默认的dimens文件了。而使用默认的尺寸的话,UI就很可能变形,简单说,就是容错机制很差。
  • 不适用于sp,当更改系统的字体大小时,字体大小不会改变。因为本质上还是用的px。
  • 包体积大。因为市面上不同宽高的屏幕很多,这里尽可能的适配所有的话,会增大包的体积,采用这种方式包体积一般增大400kb~500kb

    3.代码适配

    3.1基本原理

    image.png

    3.2常用的百分比库

    android-support-percent android官方的现已经弃用
    [AndroidAutoLayout]
    (https://github.com/hongyangAndroid/AndroidAutoLayout)鸿洋的 已停止维护
    上面两个库都已经停止维护,现在推荐用ConstraintLayout替代。

    3.3缺陷

  • 第三方的控件无效
  • 老项目更改繁琐
  • 设计图不匹配

    4.最小宽度限定符

    4.1 好处

  • 解决了比列
  • 教精确 如果有对应不上的情况,会向下找,这样的话失去了一部分精确性
  • 对应美工设计稿。因为将屏幕分成美工给定的等分

    4.2 使用

    smallestWidth适配,或者叫sw限定符适配。指的是Android会识别屏幕可用高度和宽度的最小尺寸的dp值(其实就是手机的宽度值),然后根据识别到的结果去资源文件中寻找对应限定符的文件夹下的资源文件。
    这种机制和上文提到的宽高限定符适配原理上是一样的,都是系统通过特定的规则来选择对应的文件。
    举个例子,小米5的dpi是480,横向像素是1080px,根据px=dp(dpi/160),横向的dp值是1080/(480/160),也就是360dp,系统就会去寻找是否存在value-sw360dp的文件夹以及对应的资源文件。
    image.png
    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文件中写下对应的尺寸。
    image.png
    而这种diemns引用,在不同的values-swdp文件夹下的数值是不同的,比如values-sw360dp和values-sw400dp,
    image.png
    image.png
    当系统识别到手机的smallestWidth值时,就会自动去寻找和目标数据最近的资源文件的尺寸。
    其次,从稳定性上,它也优于上述方案。原生的dp适配可能会碰到Pixel 2这种有些特别的手机需要单独适配,但是在smallestWidth适配中,通过计算Pixel 2手机的的smallestWidth的值是411,我们只需要生成一个values-sw411dp(或者取整生成values-sw410dp也没问题)就能解决问题。
    smallestWidth的适配机制由系统保证,我们只需要针对这套规则生成对应的资源文件即可,不会出现什么难以解决的问题,也根本不会影响我们的业务逻辑代码,而且只要我们生成的资源文件分布合理,,即使对应的smallestWidth值没有找到完全对应的资源文件,它也能向下兼容,寻找最接近的资源文件。

    4.3 缺陷

  • 不适配android3.2一下版本。其是android3.2以后引入的
  • 包体积过大。大约会增大300kb到800kb左右

    5.density适配

    今日头条开放出来的方案

    5.1优点

  • 解决比列问题
  • 解决设计图匹配问题
  • 很精确
  • 不影响包体积

    5.2使用

    5.2.1原理

    image.png
    从dp和px的转换公式 :px = dp * density 可以看出,如果设计图宽为360dp,想要保证在所有设备计算得出的px值都正好是屏幕宽度的话,我们只能修改 density 的值:
    image.png

    5.3缺陷

  • 如果有用到第三方库控件,则不适用。因为修改了系统的density值之后,整个布局的实际尺寸都会发生改变。

    6.其它(待更新)

参考:
Android 屏幕适配方案
一种极低成本的Android屏幕适配方式
Android 目前最稳定和高效的UI适配方案

CATALOG
  1. 1. 1.基本概念
    1. 1.1. 1.1 px
    2. 1.2. 1.2 屏幕分辨率
    3. 1.3. 1.2 ppi, dpi
    4. 1.4. 1.3 dp,sp
      1. 1.4.1. 1.3.1 dp的缺陷
  2. 2. 2.宽高限定符适配
    1. 2.1. 2.1好处
    2. 2.2. 2.2使用
    3. 2.3. 2.3缺陷
  3. 3. 3.代码适配
    1. 3.1. 3.1基本原理
    2. 3.2. 3.2常用的百分比库
    3. 3.3. 3.3缺陷
  4. 4. 4.最小宽度限定符
    1. 4.1. 4.1 好处
    2. 4.2. 4.2 使用
    3. 4.3. 4.3 缺陷
  5. 5. 5.density适配
    1. 5.1. 5.1优点
    2. 5.2. 5.2使用
      1. 5.2.1. 5.2.1原理
    3. 5.3. 5.3缺陷
  6. 6. 6.其它(待更新)