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 的引用,這時修改起來工作量非常巨大,切換成本非常高昂。

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