原文地址: http://www.itdecent.cn/p/2aded8bb6ede
以下是 騷年你的屏幕適配方式該升級了! 系列文章,歡迎轉(zhuǎn)發(fā)以及分享:
- 騷年你的屏幕適配方式該升級了!(一)-今日頭條適配方案
- 騷年你的屏幕適配方式該升級了!(二)-smallestWidth 限定符適配方案
- 今日頭條屏幕適配方案終極版正式發(fā)布!
- 為什么說 AndroidAutoLayout 的設(shè)計有問題
掃描或點擊以下二維碼,加入技術(shù)交流 QQ 群 455850365
前言
ok,根據(jù)上一篇文章 騷年你的屏幕適配方式該升級了!-今日頭條適配方案 的承諾,本文是這個系列的第二篇文章,這篇文章會詳細講解 smallestWidth 限定符屏幕適配方案
了解我的朋友一定知道,MVPArms 一直使用的是 鴻神 的 AndroidAutoLayout 屏幕適配方案,得益于 AndroidAutoLayout 的便捷,所以我對屏幕適配領(lǐng)域研究的不是很多,AndroidAutoLayout 停止維護后,我也一直在找尋著替代方案,直到 今日頭條屏幕適配方案 刷屏,后來又無意間看到了 smallestWidth 限定符屏幕適配方案,這才慢慢的將研究方向轉(zhuǎn)向了屏幕適配領(lǐng)域
最近一個月才開始慢慢惡補 Android 屏幕適配的相關(guān)知識,對這兩個方案也進行了更深入的研究,可以說從一個小白慢慢成長而來,所以我明白小白的痛,因此在上一篇文章 騷年你的屏幕適配方式該升級了!-今日頭條適配方案 中,把 今日頭條屏幕適配方案 講得非常的細,盡量把每一個知識點都描述清晰,深怕小白漏掉每一個細節(jié),這篇文章我也會延續(xù)上一篇文章的優(yōu)良傳統(tǒng),將 smallestWidth 限定符屏幕適配方案 的每一個知識點都描述清晰
順便說一句,感謝大家對 AndroidAutoSize 的支持,我只是在上一篇文章中提了一嘴我剛發(fā)布的屏幕適配框架 AndroidAutoSize,還沒給出詳細的介紹和原理剖析 (原計劃在本系列的第三篇文章中發(fā)布),AndroidAutoSize 就被大家推上了 Github Trending,一個多星期就拿了 2k+ stars,隨著關(guān)注度的增加,我在這段時間里也累壞了,issues 就沒斷過,不到半個月就提交了 200 多次 commit,但累并快樂著,在這里要再次感謝大家對 AndroidAutoSize 的認可
談談對百分比庫的看法
是這樣的,在上篇文章中有一些兄弟提了一些觀點,我很是認同,但是我站在執(zhí)行者的角度來看待這個問題,也有一些不同的觀點,以下是我在上篇文章中的回復

大家要注意了!這些觀點其實針對的是所有以百分比縮放布局的庫,而不只是今日頭條屏幕適配方案,所以這些觀點也同樣適用于 smallestWidth 限定符屏幕適配方案,這點有很多人存在誤解,所以一定要注意!

上圖的每一個方框都代表一種 Android 設(shè)備的屏幕,Android 的 系統(tǒng)碎片化、機型以及屏幕尺寸碎片化、屏幕分辨率碎片化 有多嚴重大家可以通過 友盟指數(shù) 了解一下,有些時候在某些事情的決斷標準上,并不能按照事情的對錯來決斷,大多數(shù)情況還是要分析成本,收益等多種因素,通過利弊來決斷,每個人的利弊標準又都不一樣,所以每個人的觀點也都會有差別,但也都應該得到尊重,所以我只是說說自己的觀點,也不否認任何人的觀點
方案是死的人是活的,在某些大屏手機或平板電腦上,您也可以采用其他適配方案和百分比庫結(jié)合使用,比如針對某個屏幕區(qū)間的設(shè)備單獨出一套設(shè)計圖以顯示比小屏幕手機更多更精細的內(nèi)容,來達到與百分比庫互補的效果,沒有一個方案可以說自己是完美的,但我們能清晰的認識到不同方案的優(yōu)缺點,將它們的優(yōu)點相結(jié)合,才能應付更復雜的開發(fā)需求,產(chǎn)出最好的產(chǎn)品
友情提示: 下面要介紹的 smallestWidth 限定符屏幕適配方案,原理也同樣是按照百分比縮放布局,理論上也會存在上面所說的 大屏手機和小屏手機顯示的內(nèi)容相同 的問題,選擇與否請仔細斟酌
簡介 smallestWidth 限定符適配方案
這個方案的的使用方式和我們平時在布局中引用 dimens 無異,核心點在于生成 dimens.xml 文件,但是已經(jīng)有大神幫我們做了這 一步
├── src/main
│ ├── res
│ ├── ├──values
│ ├── ├──values-800x480
│ ├── ├──values-860x540
│ ├── ├──values-1024x600
│ ├── ├──values-1024x768
│ ├── ├──...
│ ├── ├──values-2560x1440
如果有人還記得上面這種 寬高限定符屏幕適配方案 的話,就可以把 smallestWidth 限定符屏幕適配方案 當成這種方案的升級版,smallestWidth 限定符屏幕適配方案 只是把 dimens.xml 文件中的值從 px 換成了 dp,原理和使用方式都是沒變的,這些在上面的文章中都有介紹,下面就直接開始剖析原理,smallestWidth 限定符屏幕適配方案 長這樣??
├── src/main
│ ├── res
│ ├── ├──values
│ ├── ├──values-sw320dp
│ ├── ├──values-sw360dp
│ ├── ├──values-sw400dp
│ ├── ├──values-sw411dp
│ ├── ├──values-sw480dp
│ ├── ├──...
│ ├── ├──values-sw600dp
│ ├── ├──values-sw640dp
原理
其實 smallestWidth 限定符屏幕適配方案 的原理也很簡單,開發(fā)者先在項目中根據(jù)主流屏幕的 最小寬度 (smallestWidth) 生成一系列 values-sw<N>dp 文件夾 (含有 dimens.xml 文件),當把項目運行到設(shè)備上時,系統(tǒng)會根據(jù)當前設(shè)備屏幕的 最小寬度 (smallestWidth) 去匹配對應的 values-sw<N>dp 文件夾,而對應的 values-sw<N>dp 文件夾中的 dimens.xml 文字中的值,又是根據(jù)當前設(shè)備屏幕的 最小寬度 (smallestWidth) 而定制的,所以一定能適配當前設(shè)備
如果系統(tǒng)根據(jù)當前設(shè)備屏幕的 最小寬度 (smallestWidth) 沒找到對應的 values-sw<N>dp 文件夾,則會去尋找與之 最小寬度 (smallestWidth) 相近的 values-sw<N>dp 文件夾,系統(tǒng)只會尋找小于或等于當前設(shè)備 最小寬度 (smallestWidth) 的 values-sw<N>dp,這就是優(yōu)于 寬高限定符屏幕適配方案 的容錯率,并且也可以少生成很多 values-sw<N>dp 文件夾,減輕 App 的體積
什么是 smallestWidth
smallestWidth 翻譯為中文的意思就是 最小寬度,那這個 最小寬度 是什么意思呢?
系統(tǒng)會根據(jù)當前設(shè)備屏幕的 最小寬度 來匹配 values-sw<N>dp,為什么不是根據(jù) 寬度 來匹配,而要加上 最小 這兩個字呢?
這就要說到,移動設(shè)備都是允許屏幕可以旋轉(zhuǎn)的,當屏幕旋轉(zhuǎn)時,屏幕的高寬就會互換,加上 最小 這兩個字,是因為這個方案是不區(qū)分屏幕方向的,它只會把屏幕的高度和寬度中值最小的一方認為是 最小寬度,這個 最小寬度 是根據(jù)屏幕來定的,是固定不變的,意思是不管您怎么旋轉(zhuǎn)屏幕,只要這個屏幕的高度大于寬度,那系統(tǒng)就只會認定寬度的值為 最小寬度,反之如果屏幕的寬度大于高度,那系統(tǒng)就會認定屏幕的高度的值為 最小寬度
如果想讓屏幕寬度隨著屏幕的旋轉(zhuǎn)而做出改變該怎么辦呢?可以再根據(jù) values-w<N>dp (去掉 sw 中的 s) 生成一套資源文件
如果想?yún)^(qū)分屏幕的方向來做適配該怎么辦呢?那就只有再根據(jù) 屏幕方向限定符 生成一套資源文件咯,后綴加上 -land 或 -port 即可,像這樣,values-sw400dp-land (最小寬度 400 dp 橫向),values-sw400dp-port (最小寬度 400 dp 縱向)
smallestWidth 的值是怎么算的
要先算出當前設(shè)備的 smallestWidth 值我們才能知道當前設(shè)備該匹配哪個 values-sw<N>dp 文件夾
ok,還是按照上一篇文章的敘述方式,現(xiàn)在來舉栗說明,幫助大家更好理解
我們假設(shè)設(shè)備的屏幕信息是 1920 * 1080、480 dpi
根據(jù)上面的規(guī)則我們要在屏幕的高度和寬度中選擇值最小的一方作為最小寬度,1080 < 1920,明顯 1080 px 就是我們要找的 最小寬度 的值,但 最小寬度 的單位是 dp,所以我們要把 px 轉(zhuǎn)換為 dp
幫助大家再鞏固下基礎(chǔ),下面的公式一定不能再忘了!
px / density = dp,DPI / 160 = density,所以最終的公式是 px / (DPI / 160) = dp
所以我們得到的 最小寬度 的值是 360 dp (1080 / (480 / 160) = 360)
現(xiàn)在我們已經(jīng)算出了當前設(shè)備的最小寬度是 360 dp,我們曉得系統(tǒng)會根據(jù)這個 最小寬度 幫助我們匹配到 values-sw360dp 文件夾下的 dimens.xml 文件,如果項目中沒有 values-sw360dp 這個文件夾,系統(tǒng)才會去匹配相近的 values-sw<N>dp 文件夾
dimens.xml 文件是整個方案的核心所在,所以接下來我們再來看看 values-sw360dp 文件夾中的這個 dimens.xml 是根據(jù)什么原理生成的
dimens.xml 生成原理
因為我們在項目布局中引用的 dimens 的實際值,來源于根據(jù)當前設(shè)備屏幕的 最小寬度 所匹配的 values-sw<N>dp 文件夾中的 dimens.xml,所以搞清楚 dimens.xml 的生成原理,有助于我們理解 smallestWidth 限定符屏幕適配方案
說到 dimens.xml 的生成,就要涉及到兩個因數(shù),第一個因素是 最小寬度基準值,第二個因素就是您的項目需要適配哪些 最小寬度,通俗理解就是需要生成多少個 values-sw<N>dp 文件夾
第一個因素
最小寬度基準值 是什么意思呢?簡單理解就是您需要把設(shè)備的屏幕寬度分為多少份,假設(shè)我們現(xiàn)在把項目的 最小寬度基準值 定為 360,那這個方案就會理解為您想把所有設(shè)備的屏幕寬度都分為 360 份,方案會幫您在 dimens.xml 文件中生成 1 到 360 的 dimens 引用,比如 values-sw360dp 中的 dimens.xml 是長這樣的
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<dimen name="dp_1">1dp</dimen>
<dimen name="dp_2">2dp</dimen>
<dimen name="dp_3">3dp</dimen>
<dimen name="dp_4">4dp</dimen>
<dimen name="dp_5">5dp</dimen>
<dimen name="dp_6">6dp</dimen>
<dimen name="dp_7">7dp</dimen>
<dimen name="dp_8">8dp</dimen>
<dimen name="dp_9">9dp</dimen>
<dimen name="dp_10">10dp</dimen>
...
<dimen name="dp_356">356dp</dimen>
<dimen name="dp_357">357dp</dimen>
<dimen name="dp_358">358dp</dimen>
<dimen name="dp_359">359dp</dimen>
<dimen name="dp_360">360dp</dimen>
</resources>
values-sw360dp 指的是當前設(shè)備屏幕的 最小寬度 為 360dp (該設(shè)備高度大于寬度,則最小寬度就是寬度,所以該設(shè)備寬度為 360dp),把屏幕寬度分為 360 份,剛好每份等于 1dp,所以每個引用都遞增 1dp,值最大的 dimens 引用 dp_360 值也是 360dp,剛好覆蓋屏幕寬度
下面再來看看將 最小寬度基準值 定為 360 時,values-sw400dp 中的 dimens.xml 長什么樣
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<dimen name="dp_1">1.1111dp</dimen>
<dimen name="dp_2">2.2222dp</dimen>
<dimen name="dp_3">3.3333dp</dimen>
<dimen name="dp_4">4.4444dp</dimen>
<dimen name="dp_5">5.5556dp</dimen>
<dimen name="dp_6">6.6667dp</dimen>
<dimen name="dp_7">7.7778dp</dimen>
<dimen name="dp_8">8.8889dp</dimen>
<dimen name="dp_9">10.0000dp</dimen>
<dimen name="dp_10">11.1111dp</dimen>
...
<dimen name="dp_355">394.4444dp</dimen>
<dimen name="dp_356">395.5556dp</dimen>
<dimen name="dp_357">396.6667dp</dimen>
<dimen name="dp_358">397.7778dp</dimen>
<dimen name="dp_359">398.8889dp</dimen>
<dimen name="dp_360">400.0000dp</dimen>
</resources>
values-sw400dp 指的是當前設(shè)備屏幕的 最小寬度 為 400dp (該設(shè)備高度大于寬度,則最小寬度就是寬度,所以該設(shè)備寬度為 400dp),把屏幕寬度同樣分為 360份,這時每份就等于 1.1111dp 了,每個引用都遞增 1.1111dp,值最大的 dimens 引用 dp_360 同樣剛好覆蓋屏幕寬度,為 400dp
通過兩個 dimens.xml 文件的比較,dimens.xml 的生成原理一目了然,方案會先確定 最小寬度基準值,然后將每個 values-sw<N>dp 中的 dimens.xml 文件都分配與 最小寬度基準值 相同的份數(shù),再根據(jù)公式 屏幕最小寬度 / 份數(shù) (最小寬度基準值) 求出每份占多少 dp,保證不管在哪個 values-sw<N>dp 中,份數(shù) (最小寬度基準值) * 每份占的 dp 值 的結(jié)果都是剛好覆蓋屏幕寬度,所以在 份數(shù) 不變的情況下,只需要根據(jù)屏幕的寬度在不同的設(shè)備上動態(tài)調(diào)整 每份占的 dp 值,就能完成適配
這樣就能保證不管將項目運行到哪個設(shè)備上,只要當前設(shè)備能匹配到對應的 values-sw<N>dp 文件夾,那布局中的 dimens 引用就能根據(jù)當前屏幕的情況進行縮放,保證能完美適配,如果沒有匹配到對應的 values-sw<N>dp 文件夾,也沒關(guān)系,它會去尋找與之相近的 values-sw<N>dp 文件夾,雖然在這種情況下,布局中的 dimens 引用的值可能有些許誤差,但是也能保證最大程度的完成適配
說到這里,那大家就應該就會明白我為什么會說 smallestWidth 限定符屏幕適配方案 的原理也同樣是按百分比進行布局,如果在布局中,一個 View 的寬度引用 dp_100,那不管運行到哪個設(shè)備上,這個 View 的寬度都是當前設(shè)備屏幕總寬度的 360分之100,前提是項目提供有當前設(shè)備屏幕對應的 values-sw<N>dp,如果沒有對應的 values-sw<N>dp,就會去尋找相近的 values-sw<N>dp,這時就會存在誤差了,至于誤差是大是小,這就要看您的第二個因數(shù)怎么分配了
其實 smallestWidth 限定符屏幕適配方案 的原理和 今日頭條屏幕適配方案 挺像的,今日頭條屏幕適配方案 是根據(jù)屏幕的寬度或高度動態(tài)調(diào)整每個設(shè)備的 density (每 dp 占當前設(shè)備屏幕多少像素),而 smallestWidth 限定符屏幕適配方案 同樣是根據(jù)屏幕的寬度動態(tài)調(diào)整每個設(shè)備 每份占的 dp 值
第二個因素
第二個因數(shù)是需要適配哪些 最小寬度?比如您想適配的 最小寬度 有 320dp、360dp、400dp、411dp、480dp,那方案就會為您的項目生成 values-sw320dp、values-sw360dp、values-sw400dp、values-sw411dp、values-sw480dp 這幾個資源文件夾,像這樣??
├── src/main
│ ├── res
│ ├── ├──values
│ ├── ├──values-sw320dp
│ ├── ├──values-sw360dp
│ ├── ├──values-sw400dp
│ ├── ├──values-sw411dp
│ ├── ├──values-sw480dp
方案會為您需要適配的 最小寬度,在項目中生成一系列對應的 values-sw<N>dp,在前面也說了,如果某個設(shè)備沒有為它提供對應的 values-sw<N>dp,那它就會去尋找相近的 values-sw<N>dp,但如果這個相近的 values-sw<N>dp 與期望的 values-sw<N>dp 差距太大,那適配效果也就會大打折扣
那是不是 values-sw<N>dp 文件夾生成的越多,覆蓋越多市面上的設(shè)備,就越好呢?
也不是,因為每個 values-sw<N>dp 文件夾其實都會占用一定的 App 體積,values-sw<N>dp 文件夾越多,App 的體積也就會越大
所以一定要合理分配 values-sw<N>dp,以越少的 values-sw<N>dp 文件夾,覆蓋越多的機型
驗證方案可行性
原理講完了,我們還是按照老規(guī)矩,來驗證一下這個方案是否可行?
假設(shè)設(shè)計圖總寬度為 375 dp,一個 View 在這個設(shè)計圖上的尺寸是 50dp * 50dp,這個 View 的寬度占整個設(shè)計圖寬度的 13.3% (50 / 375 = 0.133)
在使用 smallestWidth 限定符屏幕適配方案 時,需要提供 最小寬度基準值 和需要適配哪些 最小寬度,我們就把 最小寬度基準值 設(shè)置為 375 (和 設(shè)計圖 一致),這時方案就會為我們需要適配的 最小寬度 生成對應的 values-sw<N>dp 文件夾,文件夾中的 dimens.xml 文件是由從 1 到 375 組成的 dimens 引用,把所有設(shè)備的屏幕寬度都分為 375 份,所以在布局文件中我們應該把這個 View 的高寬都引用 dp_50
下面就來驗證下在使用 smallestWidth 限定符屏幕適配方案 的情況下,這個 View 與屏幕寬度的比例在分辨率不同的設(shè)備上是否還能保持和設(shè)計圖中的比例一致
驗證設(shè)備 1
設(shè)備 1 的屏幕總寬度為 1080 px,屏幕總高度為 1920 px,DPI 為 480
設(shè)備 1 的屏幕高度大于屏幕寬度,所以 設(shè)備 1 的 最小寬度 為屏幕寬度,再根據(jù)公式 px / (DPI / 160) = dp,求出 設(shè)備 1 的 最小寬度 的值為 360 dp (1080 / (480 / 160) = 360)
根據(jù) 設(shè)備 1 的 最小寬度 應該匹配的是 values-sw360dp 這個文件夾,假設(shè) values-sw360dp 文件夾及里面的 dimens.xml 已經(jīng)生成,且是按 最小寬度基準值 為 375 生成的,360 / 375 = 0.96,所以每份占的 dp 值為 0.96,dimens.xml 里面的內(nèi)容是長下面這樣的??
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<dimen name="dp_1">0.96dp</dimen>
<dimen name="dp_2">1.92dp</dimen>
<dimen name="dp_3">2.88dp</dimen>
<dimen name="dp_4">3.84dp</dimen>
<dimen name="dp_5">4.8dp</dimen>
...
<dimen name="dp_50">48dp</dimen>
...
<dimen name="dp_371">356.16dp</dimen>
<dimen name="dp_372">357.12dp</dimen>
<dimen name="dp_373">358.08dp</dimen>
<dimen name="dp_374">359.04dp</dimen>
<dimen name="dp_375">360dp</dimen>
</resources>
可以看到這個 View 在布局中引用的 dp_50,最終在 values-sw360dp 中定格在了 48 dp,所以這個 View 在 設(shè)備 1 上的高寬都為 48 dp,系統(tǒng)最后會將高寬都換算成 px,根據(jù)公式 dp * (DPI / 160) = px,所以這個 View 的高寬換算為 px 后等于 144 px (48 * (480 / 160) = 144)
144 / 1080 = 0.133,View 的實際寬度與 屏幕總寬度 的比例和 View 在設(shè)計圖中的比例一致 (50 / 375 = 0.133),所以完成了等比例縮放
某些設(shè)備的高寬是和 設(shè)備 1 相同的,但是 DPI 可能不同,而由于 smallestWidth 限定符屏幕適配方案 并沒有像 今日頭條屏幕適配方案 一樣去自行修改 density,所以系統(tǒng)就會使用默認的公式 DPI / 160 求出 density,density 又會影響到 dp 和 px 的換算,因此 DPI 的變化,是有可能會影響到 smallestWidth 限定符屏幕適配方案 的
所以我們再來試試在這種特殊情況下 smallestWidth 限定符屏幕適配方案 是否也能完成適配
驗證設(shè)備 2
設(shè)備 2 的屏幕總寬度為 1080 px,屏幕總高度為 1920 px,DPI 為 420
設(shè)備 2 的屏幕高度大于屏幕寬度,所以 設(shè)備 2 的 最小寬度 為屏幕寬度,再根據(jù)公式 px / (DPI / 160) = dp,求出 設(shè)備 2 的 最小寬度 的值為 411.429 dp (1080 / (420 / 160) = 411.429)
根據(jù) 設(shè)備 2 的 最小寬度 應該匹配的是 values-sw411dp 這個文件夾,假設(shè) values-sw411dp 文件夾及里面的 dimens.xml 已經(jīng)生成,且是按 最小寬度基準值 為 375 生成的,411 / 375 = 1.096,所以每份占的 dp 值為 1.096,dimens.xml 里面的內(nèi)容是長下面這樣的??
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<dimen name="dp_1">1.096dp</dimen>
<dimen name="dp_2">2.192dp</dimen>
<dimen name="dp_3">3.288dp</dimen>
<dimen name="dp_4">4.384dp</dimen>
<dimen name="dp_5">5.48dp</dimen>
...
<dimen name="dp_50">54.8dp</dimen>
...
<dimen name="dp_371">406.616dp</dimen>
<dimen name="dp_372">407.712dp</dimen>
<dimen name="dp_373">408.808dp</dimen>
<dimen name="dp_374">409.904dp</dimen>
<dimen name="dp_375">411dp</dimen>
</resources>
可以看到這個 View 在布局中引用的 dp_50,最終在 values-sw411dp 中定格在了 54.8dp,所以這個 View 在 設(shè)備 2 上的高寬都為 54.8 dp,系統(tǒng)最后會將高寬都換算成 px,根據(jù)公式 dp * (DPI / 160) = px,所以這個 View 的高寬換算為 px 后等于 143.85 px (54.8 * (420 / 160) = 143.85)
143.85 / 1080 = 0.133,View 的實際寬度與 屏幕總寬度 的比例和 View 在設(shè)計圖中的比例一致 (50 / 375 = 0.133),所以完成了等比例縮放
雖然 View 在 設(shè)備 2 上的高寬是 143.85 px,比 設(shè)備 1 的 144 px 少了 0.15 px,但是誤差非常小,整體的比例并沒有發(fā)生太大的變化,是完全可以接受的
這個誤差是怎么引起的呢,因為 設(shè)備 2 的 最小寬度 的實際值是 411.429 dp,但是匹配的 values-sw411dp 舍去了小數(shù)點后面的位數(shù) (切記!系統(tǒng)會去尋找小于或等于 411.429 dp 的 values-sw<N>dp,所以 values-sw412dp 這個文件夾,設(shè)備 2 是匹配不了的),所以才存在了一定的誤差,因此上面介紹的第二個因數(shù)是非常重要的,這直接決定誤差是大還是小
可以看到即使在高寬一樣但 DPI 不一樣的設(shè)備上,smallestWidth 限定符屏幕適配方案 也能完成等比例適配,證明這個方案是可行的,如果大家還心存疑慮,也可以再試試其他分辨率的設(shè)備,其實到最后得出的比例都是在 0.133 左右,唯一的變數(shù)就是第二個因數(shù),如果您生成的 values-sw<N>dp 與設(shè)備實際的 最小寬度 差別不大,那誤差也就在能接受的范圍內(nèi),如果差別很大,那就直接 GG
優(yōu)點
非常穩(wěn)定,極低概率出現(xiàn)意外
不會有任何性能的損耗
適配范圍可自由控制,不會影響其他三方庫
在插件的配合下,學習成本低
缺點
在布局中引用 dimens 的方式,雖然學習成本低,但是在日常維護修改時較麻煩
侵入性高,如果項目想切換為其他屏幕適配方案,因為每個 Layout 文件中都存在有大量 dimens 的引用,這時修改起來工作量非常巨大,切換成本非常高昂
無法覆蓋全部機型,想覆蓋更多機型的做法就是生成更多的資源文件,但這樣會增加 App 體積,在沒有覆蓋的機型上還會出現(xiàn)一定的誤差,所以有時需要在適配效果和占用空間上做一些抉擇
如果想使用 sp,也需要生成一系列的 dimens,導致再次增加 App 的體積
不能自動支持橫豎屏切換時的適配,如上文所說,如果想自動支持橫豎屏切換時的適配,需要使用 values-w<N>dp 或 屏幕方向限定符 再生成一套資源文件,這樣又會再次增加 App 的體積
不能以高度為基準進行適配,考慮到這個方案的名字本身就叫 最小寬度限定符適配方案,所以在使用這個方案之前就應該要知道這個方案只能以寬度為基準進行適配,為什么現(xiàn)在的屏幕適配方案只能以高度或?qū)挾绕渲械囊粋€作為基準進行適配,請看 這里
使用中的問題
這時有人就會問了,設(shè)計師給的設(shè)計圖只標注了 px,使用這個方案時,那不是還要先將 px 換算成 dp?
其實也可以不用換算的,那這是什么騷操作呢?
很簡單,你把設(shè)計圖的 px 總寬度設(shè)置成 最小寬度基準值 就可以了,還是以前面驗證可行性的例子
我們在前面驗證可行性時把 最小寬度基準值 設(shè)置成了 375,為什么是 375 呢?因為設(shè)計圖的總寬度為 375 dp,如果換算成 px,總寬度就是 750 px,我們這時把 最小寬度基準值 設(shè)置成 750,然后看看 values-sw360dp 中的 dimens.xml 長什么樣??
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<dimen name="px_1">0.48dp</dimen>
<dimen name="px_2">0.96dp</dimen>
<dimen name="px_3">1.44dp</dimen>
<dimen name="px_4">1.92dp</dimen>
<dimen name="px_5">2.4dp</dimen>
...
<dimen name="px_50">24dp</dimen>
...
<dimen name="px_100">48dp</dimen>
...
<dimen name="px_746">358.08dp</dimen>
<dimen name="px_747">358.56dp</dimen>
<dimen name="px_748">359.04dp</dimen>
<dimen name="px_749">359.52dp</dimen>
<dimen name="px_750">360dp</dimen>
</resources>
360 dp 被分成了 750 份,相比之前的 375 份,現(xiàn)在 每份占的 dp 值 正好減少了一半,還記得在驗證可行性的例子中那個 View 的尺寸是多少嗎?50dp * 50dp,如果設(shè)計圖只標注 px,那這個 View 在設(shè)計圖上的的尺寸應該是 100px * 100px,那我們直接根據(jù)設(shè)計圖上標注的 px,想都不用想直接在布局中引用 px_100 就可以了,因為在 375 份時的 dp_50 剛好等于 750 份時的 px_100 (值都是 48 dp),所以這時的適配效果和之前驗證可行性時的適配效果沒有任何區(qū)別
看懂了嗎?直接將 最小寬度基準值 和布局中的引用都以 px 作為單位就可以直接填寫設(shè)計圖上標注的 px!
總結(jié)
關(guān)于文中所列出的優(yōu)缺點,列出的缺點數(shù)量確實比列出的優(yōu)點數(shù)量多,但 缺點 3,缺點 4,缺點 5 其實都可以歸納于 占用 App 體積 這一個缺點,因為他們都可以通過增加資源文件來解決問題,而 缺點 6 則是這個方案的特色,只能以寬度為基準進行適配,這個從這個方案的名字就能看出
請大家千萬不要曲解文章的意思,不要只是單純的對比優(yōu)缺點的數(shù)量,缺點的數(shù)量大于優(yōu)點的數(shù)量就一定是這個方案不行?沒有一個方案是完美的,每個人的需求也都不一樣,作為一篇科普類文章我只可能把這個方案描述得盡可能的全面
這個方案能給你帶來什么,不能給你帶來什么,我必須客觀的描述清楚,這樣才有助你做出決定,你應該注重的是在這些優(yōu)缺點里什么是我能接受的,什么是我不能接受的,是否能為了某些優(yōu)點做出某些妥協(xié),而不只是單純的去看數(shù)量,這樣毫無意義,有些人就是覺得穩(wěn)定性最重要,其他的都可以做出妥協(xié),那其他缺點對于他來說都是無所謂的
好了,這個系列的第二篇文章講完了,這篇文章也是按照上篇文章的優(yōu)良傳統(tǒng),寫的非常詳細,哪怕是新手我相信也應該能看懂,為什么這么多人都不知道自己該選擇什么樣的方案,就是因為自己都沒搞懂這些方案的原理,懂了原理過后才知道這些方案是否是自己想要的
接下來的第三篇文章會詳細講解兩個方案的深入對比以及該如何選擇,并剖析我根據(jù) 今日頭條屏幕適配方案 優(yōu)化的屏幕適配框架 AndroidAutoSize 的原理,敬請期待
如果大家想使用 smallestWidth 限定符屏幕適配方案,可以參考 這篇文章,里面提供有自動生成資源文件的插件和 Demo,由于我并沒有在項目中使用 smallestWidth 限定符屏幕適配方案,所以如果在文章中有遺漏的知識點請諒解以及補充,感謝!
公眾號
掃碼關(guān)注我的公眾號 JessYan,一起學習進步,如果框架有更新,我也會在公眾號上第一時間通知大家
以下是 騷年你的屏幕適配方式該升級了! 系列文章,歡迎轉(zhuǎn)發(fā)以及分享:
- 騷年你的屏幕適配方式該升級了!(一)-今日頭條適配方案
- 騷年你的屏幕適配方式該升級了!(二)-smallestWidth 限定符適配方案
- 今日頭條屏幕適配方案終極版正式發(fā)布!
- 為什么說 AndroidAutoLayout 的設(shè)計有問題
Hello 我叫 JessYan,如果您喜歡我的文章,可以在以下平臺關(guān)注我
- 個人主頁: http://jessyan.me
- GitHub: https://github.com/JessYanCoding
- 掘金: https://juejin.im/user/57a9dbd9165abd0061714613
- 簡書: http://www.itdecent.cn/u/1d0c0bc634db
- 微博: http://weibo.com/u/1786262517
-- The end