Android屏幕适配方案总结

一、基础知识

1.Android中常用的距离单位

  • px(像素):每个px对应屏幕上的一个点。

  • dip或dp:(device independent pixels,设备独立像素):一种基于屏幕密度的抽象单位。在每英寸160点的显示器上,1dip=1px.单随着屏幕的密度改变,dip和px的换算也会发生改变

  • sp(scaled pixels, 比例像素):主要处理字体的大小,可以根据用户的字体大小首选项进行缩放。

  • in(英寸):标准长度单位,1 英寸=2.54 厘米。

  • mm(毫米):标准长度单位。

  • pt(磅):标准的长度单位, 1/72英寸。

2.重要概念

2.1 屏幕尺寸
  • 含义:手机对角线的物理尺寸
  • 单位:英寸(inch),1英寸=2.54cm
2.2 屏幕分辨率
  • 含义:手机在横向、纵向上的像素点数总和
  • 例子:1920x1080,即高度方向上有1920个像素点,宽度方向上有1080个像素点
  • 单位:px(pixel),1px=1像素点
  • Android手机常见的分辨率:320x480、480x800、720x1280、1080x1920
2.3 屏幕像素密度
  • 含义:每英寸的像素点数
  • 单位:dpi(dots per ich)
  • 安卓手机对于每类手机屏幕大小都有一个相应的屏幕像素密度:
密度类型 代表的分辨率(px) 屏幕像素密度(dpi) 换算(px/dp)
低密度(ldpi) 240x320 120 1dp=0.75px
中密度(mdpi) 320x480 160 1dp=1px
高密度(hdpi) 480x800 240 1dp=1.5px
超高密度(xhdpi) 720x1280 320 1dp=2px
超超高密度(xxhdpi) 1080x1920 480 1dp=3px
2.4 屏幕尺寸、分辨率、像素密度三者关系

https://upload-images.jianshu.io/upload_images/944365-2b5dc928ab334440.png?imageMogr2/auto-orient/strip|imageView2/2/w/360


二、目前流行的屏幕适配方案

1.今日头条适配方案

使用的原生api介绍:

android中的dp在渲染前会将dp转为px,计算公式:
px = density * dp;
density = dpi / 160;
px = dp * (dpi / 160);
density 是 DisplayMetrics 中的成员变量
DisplayMetrics#density 就是上述的density
DisplayMetrics#densityDpi 就是上述的dpi
DisplayMetrics#scaledDensity 字体的缩放因子,正常情况下和density相等,但是调节系统字体大小后会改变这个值

对dp的总结:

  1. 两个屏幕物理宽度相等,则两个屏幕的总宽度dp也相等
  2. dp作用是保持相同dp的大小在不同分辨率不同像素密度的屏幕上展示的实际大小一致,但是就造成了大小跟屏幕比例的不同
  3. dp等于物理定长:因为160像素密度下1dp=1px,而像素密度是1英寸包含的像素数,因此160像素密度下 1英寸=160px=160dp,所以 1dp=(1/160*)(inch)=(2.54/160)(cm)

今日头条方案总结:

  • 修改density 保持屏幕总宽度dp不变,将density的计算方法 从根据像素密度/160 改成了 屏幕像素宽度/屏幕的目标宽度dp。原来的density的作用是换算出不同情况下dp对应的px,达到如上面描述dp的效果,而方案修改后的density的作用是实现相同的dp大小的view在屏幕中所占比例相同。也就导致了屏幕总宽度dp变大没有展示更多的内容,而是放大了view,跟原来展示内容一样多。
  • 也可以理解为:根据ui设计图的宽度dp值,算出当前屏幕每dp占当前屏幕多少像素值(也就是所说的density)

2.smallestWidth限定符适配方案

总结:

  • 其实 smallestWidth 限定符屏幕适配方案 的原理和 今日头条屏幕适配方案 挺像的,今日头条屏幕适配方案 是根据屏幕的宽度或高度动态调整每个设备的 density (每 dp 占当前设备屏幕多少像素),而 smallestWidth 限定符屏幕适配方案 同样是根据屏幕的宽度动态调整每个设备 每份占的 dp 值
  • 也可以理解为:根据ui设计图的宽度dp值,算出当前屏幕分成ui设计图的宽度dp份后,每dp占当前屏幕实际多少dp,然后这个实际dp值再根据dpi转换成具体像素值

3.使用pt作长度单位的适配方案

首先科普下 Android 中的一个长度单位:pt,它表示一个点,是屏幕的物理尺寸,其大小为 1 英寸的 1 / 72,也就是 72pt 等于 1 英寸(其实 Android 中还有比较少见的 in 和 mm 的长度单位)。

原理其实也是基于头条的原理,不过是操作 pt,所以不是改 DisplayMetrics#density,而是 DisplayMetrics#xdpi,系统不同单位换算为px代码如下:

public static float applyDimension(int unit, float value,
                                       DisplayMetrics metrics)
    {
        switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
        return 0;
    }

至于为什么不使用in或者mm,作者回答是“尺寸太大了,pt 比较适中”。

三、总结

三种方案各自的优缺点:方案比较

目前推荐使用第一、三种方案,因为第二个smallestWidth限定符适配方案侵入性太高,如果项目想切换为其他屏幕适配方案,因为每个 Layout 文件中都存在有大量 dimens 的引用,这时修改起来工作量非常巨大,切换成本非常高昂。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章