Android開發過程當中咱們經常使用的尺寸單位有px、dp,還有一種sp通常是用於字體的大小。可是因爲px是像素單位,好比咱們一般說的手機分辨例如1920*1080都是px的單位。如今Android屏幕分辨率碎片化720x1280、1080x1920、2280x1080,這就形成例如187px會在各個分辨率的機型上都是顯示同樣大小的,那確定不是咱們想要的效果,因此用px單位咱們是難以達到適配效果的,那麼爲何用dp能夠呢?android
使用px單位從左到右依次爲 480 * 800、1080 * 1920、1440 * 2560api
使用dp單位從左到右依次爲 480 * 800、1080 * 1920、1440 * 2560bash
屏幕總寬度依次爲 320dp、415dp、411dppost
dp指的是設備獨立像素,以dp爲尺寸單位的控件,在不一樣分辨率和尺寸的手機上表明瞭不一樣的真實像素,好比在分辨率較低的手機中,可能1dp=1px,而在分辨率較高的手機中,可能1dp=2px,這樣的話,一個187dp高度的控件,在不一樣的手機中就能表現出差很少的大小了。性能
android中的dp在渲染前會將dp轉爲px,計算公式:學習
px = density * dp;字體
density = dpi / 160;spa
px = dp * (dpi / 160);插件
而dpi是根據屏幕真實的分辨率和尺寸來計算的,每一個設備均可能不同的。設計
因爲density不是固定不變的,因此每一個分辨率不一樣的設備他們的density都確定不相等,這樣就會形成每一個設備的寬/高對應的總dp都是不一樣的,假設480 * 800分辨率的density是1.5,1080 * 1920分辨率的density是2.6,1440 * 2560分辨率的density是3.5。那麼它們對應的寬度總dp = (寬度px) / density,分別爲320dp、415dp、411dp。能夠看出單位爲dp的時候三個設備之間的差距就不是很大了,可是這樣確定仍是不能知足咱們對屏幕適配的要求的。下面來看看Android常見的三種比較成熟的屏幕適配方案,並分析這幾種方案的優劣。
設定一個基準的分辨率,也就是設計圖對應的分辨率,其餘分辨率都根據這個基準分辨率來計算,在不一樣的尺寸文件夾內部,根據該尺寸編寫對應的dimens文件。
好比咱們的設計圖 375 * 667爲基準分辨率
寬度爲375,將任何分辨率的寬度整分爲375份,取值爲x1-x375
高度爲667,將任何分辨率的高度整分爲667份,取值爲y1-y667
那麼對於1080*1920的分辨率的dimens文件來講,
x1=(1080/375)*1=2.88px
x2=(1080/375)*2=5.76px
y1=(1920/667)*1=2.87px
y2=(1920/667)*2=5.75px
當代碼裏面引用高度爲y_187,在APP運行時會根據當前設備分辨率去找對應xml文件中對應的高度,咱們就能夠按照設計稿上的尺寸填寫相對應的dimens引用了,這樣基本解決了咱們的適配問題,並且極大的提高了咱們UI開發的效率。
簡單經過計算驗證下這種方案是否能達到適配的效果,例如設計圖上有一個寬187dp的View。
480 * 800
設計圖佔寬比: 187dp / 375dp = 0.498
實際在480 * 800佔寬比 = 187 * 1.28px / 480 = 0.498
1080 * 1920
設計圖佔寬比: 187dp / 375dp = 0.498
實際在1080 * 1920佔寬比 = 187 * 2.88px / 1080 = 0.498
計算高同理
可是這個方案有一個致命的缺陷,那就是須要精準命中才能適配,好比1920x1080的手機就必定要找到1920x1080的限定符,不然就只能用統一的默認的dimens文件了。而使用默認的尺寸的話,UI就極可能變形,簡單說,就是容錯機制不好。
smallestWidth適配,或者叫sw限定符適配。指的是Android會識別屏幕可用高度和寬度的最小尺寸的dp值(其實就是手機的寬度值),而後根據識別到的結果去資源文件中尋找對應限定符的文件夾下的資源文件。
這種機制和上文提到的寬高限定符適配原理上是同樣的,都是系統經過特定的規則來選擇對應的文件。
能夠把 smallestWidth 限定符屏幕適配方案 當成這種方案的升級版,smallestWidth 限定符屏幕適配方案 只是把 dimens.xml 文件中的值從 px 換成了 dp,原理和使用方式都是沒變的
├── src/main
│ ├── res
│ ├── ├──values
│ ├── ├──values-sw320dp
│ ├── ├──values-sw360dp
│ ├── ├──values-sw400dp
│ ├── ├──values-sw411dp
│ ├── ├──values-sw480dp
│ ├── ├──...
│ ├── ├──values-sw600dp
│ ├── ├──values-sw640dp
複製代碼
1920 * 1080分辨率的手機,dpi爲420,咱們一樣設置一個View爲187dp寬
1440 * 2560分辨率的手機,dpi爲560,咱們一樣設置一個View爲187dp寬
由於識別的文件夾是values-sw410dp的文件夾,可是屏幕寬度爲415dp和411dp,因此最後計算出的佔比會有一點點偏差,基本能夠忽略不計,能夠達到相對比較準確的適配效果
今日頭條屏幕適配方案的核心原理在於,根據如下公式算出 density
默認px = density * dp,也就是屏幕總寬度dp = 屏幕寬度px / density,這個時候咱們假設全部設備上的屏幕總寬度dp會等於咱們設計圖375dp,那麼能夠得出一個公式:
density = 屏幕寬度px / 設計圖寬度(375dp)
而後咱們經過系統api,將density賦值給系統,拋棄掉系統默認計算density的計算公式。
這樣能夠很巧妙的實現屏幕適配,並且侵入性極低,甚至能夠忽略不計。
1920 * 1080分辨率的手機,咱們一樣設置一個View爲187dp寬,設計圖寬度爲375dp
1440 * 2560分辨率的手機,咱們一樣設置一個View爲187dp寬,設計圖寬度爲375dp
能夠看出,這種方案是徹底沒有偏差的,並且侵入性極低,只須要修改系統的density。雖然修改系統的density屬性會產生一小部分影響,可是基本都是很好解決的。