首先聲明一點這個並非一個新的屏幕適配方案,其適配原理爲SmallWidth,正如其名字同樣,但願經過這個框架適配,讓SmallWidth適配方案變得更加容易。android
2018年的時候今日頭條公佈的他們的屏幕適配方案,緊接着各位大佬也陸續發佈了屏幕適配的相關文章,同時 JessYan 還發布了今日頭條方案的適配框架,這些都極大地幫助android開發者可以更加容易的進行屏幕適配。在全部的屏幕適配方案中,公認比較好的屏幕適配方案有基於最小寬度 SmallWidth和 基於頭條適配方案的 AndroidAutoSize。github
咱們都知道手機屏幕的顯示是經過一個個像素來完成的,可是android並不推薦咱們直接使用px來標記ui大小。由於不一樣的手機分辨率不一樣。相同的像素在越高的分辨率的手機上顯示越小。api
android推薦使用dp來進行屏幕適配。markdown
那麼什麼是dp?app
dp指的是設備獨立像素,以dp爲尺寸單位的控件,在不一樣分辨率和尺寸的手機上表明瞭不一樣的真實像素,好比在分辨率較低的手機中,可能1dp=1px,而在分辨率較高的手機中,可能1dp=2px,這樣的話,一個96*96dp的控件,在不一樣的手機中就能表現出差很少的大小了。框架
dp與px的關係eclipse
咱們都知道一個公式: px = dp(dpi/160) 系統都是經過這個來判斷px和dp的數學關係,ide
那麼這裏又出現了一個問題,oop
dpi是什麼呢?
dpi是像素密度,指的是在系統軟件上指定的單位尺寸的像素數量,它每每是寫在系統出廠配置文件的一個固定值。
dpi的計算方式:
系統的dp可以解決大部分的問題,可是因爲手機生產廠家的不一樣,系統的dpi就有可能不一樣,爲了解決寬度相同像素不一樣dpi手機的適配問題,咱們須要用到屏幕適配方案。
SmallWidth基於當前設備的寬度,從大到小一次查找最接近的dimen資源 進行使用。假設當前設備的寬度360dp 存在sw361dp,sw350dp。即便sw361dp和設備的寬度360dp接近。也會使用sw350dp的資源
SmallWodth是一種等比例適配方案,假設咱們以360dp爲設計寬度,那麼在360dp的dimens中的 值該如何編寫呢?在咱們的設計中360dp能鋪滿全屏,那麼在如今350dp也能鋪滿全屏。
即:若是 350中的dimen值/350 = 360dimen中的值/360 那麼他們在不一樣設備的所佔比例是相同的,ui看起來就是相同的。換言之在 在sw XXXdp中的值 = XXX/設計目標尺寸。
以最sw360dp 爲例,在sw360中 所佔dp 爲10
在sw350中佔用多少dp? = 10 * 350/360 = 9.72dp
在sw400中佔用多少dp? = 10 * 400/360 = 11.11dp
SmallWidth的優缺點:
優勢:穩定,對app沒有性能損耗,適配範圍可控,不會影響其餘三方庫
缺點:dimens維護成本較高;方案侵入性大。適配方案切換起來很是麻煩;致使app體積增大。
今日頭條適配方案能夠說是屏幕適配的終極應用。其原理以下。若是想讓設計圖上的ui在全部設備上看起來都差很少,以款或者高爲基準進行等比例變化。就須要讓下面的等式成立。
以寬度爲基準舉例:
設計圖尺寸 X(單位dp)/設計圖寬度DW(單位 dp) = ui實際佔用 Y (單位px)/ 屏幕寬度W(單位px)
咱們知道:在android中 ui實際像素y = X * 設備獨立密度M
即上面的等式能夠轉換成
X / DW = M * X / W
這樣就能夠獲得頭條的適配方案公式 M = W / DW
即:當前設備屏幕總寬度(單位爲像素)/ 設計圖總寬度(單位爲 dp) = density
優缺點:
優勢:使用成本低,一鍵接入。不會有性能損耗。
缺點:對三方庫兼容性很差。
適配方案/對比角度 | SmallWidth | AndroidAutoSize |
---|---|---|
穩定性 | 基於系統原理適配很是穩定 | 經過修改設備獨立密度進行適配 ,由於是公共api,任何人均可以更改,存在必定的風險。可是隨着框架的演進。基本上能夠不考慮這方面對屏幕適配形成的影響 |
維護 | 一點有dimen值增長或者修改,須要維護多個文件 | 在三方庫使用很少的狀況維護簡單,若是有較多的 三方庫。維護困難 |
對三方庫的兼容下 | 適配範圍可控,不會影響三方庫 | 除非三方庫與本身設計圖尺寸相同不然與三方庫不兼容 |
性能 | 會增長許多適配文件,形成app體積增大 | 基本無影響 |
能夠看到AndroidAutoSize相較於SmallWidth優點仍是比較明顯,若是在三方庫使用比較少的狀況下,是很是不錯的。可是正如AndroidAutoSize做者所提到的同樣,若是使用較多的三方庫,不兼容問題將是災難性的。
缺點
暫時沒發現其餘什麼很明顯的缺點,已知的缺點有一個,那就是第三個優勢,它既是這個方案的優勢也一樣是缺點,可是就這一個缺點也是很是致命的
只須要修改一次 density,項目中的全部地方都會自動適配,這個看似解放了雙手,減小了不少操做,可是實際上反應了一個缺點,那就是隻能一刀切的將整個項目進行適配,但適配範圍是不可控的
這樣不是很好嗎?這樣原本是很好的,可是應用到這個方案是就很差了,由於我上面的原理也分析了,這個方案依賴於設計圖尺寸,可是項目中的系統控件、三方庫控件、等非咱們項目自身設計的控件,它們的設計圖尺寸並不會和咱們項目自身的設計圖尺寸同樣
當這個適配方案不分類型,將全部控件都強行使用咱們項目自身的設計圖尺寸進行適配時,這時就會出現問題,當某個系統控件或三方庫控件的設計圖尺寸和和咱們項目自身的設計圖尺寸差距很是大時,這個問題就越嚴重
也就是說在說用較多三方庫的時候建議用SmallWidth,不然就使用AutoSize。
經過上面的對比咱們發現,在使用較多的三方庫時,基本上不可能選擇AndroidAutoSize。咱們只能使用SmallWidth,那麼咱們也就只能接受SmallWidth的全部缺點了嗎?
在使用SmallWidth的過程當中咱們最大的問題是維護困難。而EasySmallWidth就是爲了解決SmallWidth的維護問題而產生的。
AndroidStudio經過Gradle進行打包,會通過 Initialization、Configuration、Execution 三個階段。在configuration會讀取全部項目的配置,並最終生成Gradle TASK執行的有相圖。EasySmallWidth就是在Gradle 讀取項目配置以後,生成有相圖以前,插入自定義Task,讓咱們須要的dimens文件,先於構建Apk。經過觀察Gradle打包生成apk的Task,不管是Android library 仍是android application 在執行task以前都會執行 preBuild Task 。所以EasySmallWidth選取PreBuild做爲插入點。進行適配工做。
屬性 | 做用 | 默認值 |
---|---|---|
enableAdapter | 是否開啓適配 true 開啓,false 關閉 | true |
defaultDesignWidth | 默認設計圖寬度 | 360f |
resPath | res相對 當前模塊的路徑。系統會根據res查找默認的dimen文件,而後建立在此路徑下建立values-swxxxdp文件。考慮到項目可能從eclipse遷移過來。增長這個配置項 | /src/main/res/ |
needToAdaptedWidth | 須要適配的最小寬度,須要本身添加 | size爲0的set |
conversionMap | 須要自定義轉換的dimens文件,默認不須要填寫。 | 以Integer爲Key,Float爲value空map |
EasySmallWidth包含二級配置,整體配置,模塊配置。具體的配置參考EasySmallWidth的使用step3。當沒有模塊配置的時候,會使用整體配置 。
step1:
在根目錄的build.gradle添加下面的代碼
classpath 'com.txl.EasySmallWidth:easySmallWidth:1.0.0'
複製代碼
step2: 引入插件
項目的入口引入插件,EasySmallWidth會自動遍歷當前項目的 全部模塊併爲它添加適配任務,因此不須要在 每一個模塊重複引用插件
apply plugin: 'BuildAdaptionPlugin'
複製代碼
插件引入成功後在模塊的中能夠看到EasySmallWidth爲每一個 模塊添加的建立和刪除適配文件的task
若是Android Studio 沒有顯示task 從新設置下下面的屬性便可
step3:添加配置項
adaptionAppExtension{
defaultDesignWidth = 360f //默認設計圖的寬度爲360dp
enableAdapter = true //開啓屏幕適配
needToAdaptedWidth.add(400) // 須要適配最小寬度400dp 即會建立values-sw400dp
needToAdaptedWidth.add(411) // 須要適配最小寬度411dp 即會建立values-sw411dp
needToAdaptedWidth.add(441) // 須要適配最小寬度441dp 即會建立values-sw441dp
// res路徑,默認不用配置
// resPath = "${File.separator}src${File.separator}main${File.separator}res${File.separator}"
//針對testAutoBuildDimen 模塊建立獨自的配置
def ex = createBuildAdaptionPluginExtension(project,adaptionAppExtension,"testAutoBuildDimen")
//對模塊testAutoBuildDimen sw400與默認值的轉換關係爲 實際值*1.0
ex.conversionMap.put(400,1.0f)
//對模塊testAutoBuildDimen sw400與默認值的轉換關係爲 實際值*2.0
ex.conversionMap.put(411,2.0f)
//對模塊testAutoBuildDimen sw400與默認值的轉換關係爲 實際值*3.0
ex.conversionMap.put(441,3.0f)
def aeasy = createBuildAdaptionPluginExtension(project,adaptionAppExtension,"aeasybuild")
//aeasy 模塊的默認寬度是375dp
aeasy.defaultDesignWidth = 375f
}
複製代碼
直接經過android studio 進行編譯,而後在對應模塊下就會產生對應的dimens文件
app模塊:
能夠看到 sw400dp中的 dimen值 = 400/360 * 實際值 符合SmallWidth要求
aeasybuild模塊:
能夠看到 sw400dp中的 dimen值 = 400/375 * 實際值 符合SmallWidth要求 (咱們在配置的時候將aeasybuild的默認寬度設置成立375dp)
testAutoBuildDimen模塊:
爲何這個模塊的值不是按照smallWidth來的呢?由於咱們在前面配置的時候對它作了自定義轉換,sw400與設計圖1.0倍處理
缺點:
優勢:
能夠這樣說EasySmallWidth作爲SmallWidth的升級版,主要的職責就是解決SmallWidth的維護性 和代碼入侵的問題。
由於如今流行的AutoSize與SmallWidth之間不兼容,建議三方庫不進行屏幕適配,對外公佈本身的設計圖尺寸,同時將默認的dimen文件發不出來。具體的適配工做交給開發者本身選擇。