原文地址: http://www.itdecent.cn/p/4aa23d69d481
以下是 騷年你的屏幕適配方式該升級(jí)了! 系列文章,歡迎轉(zhuǎn)發(fā)以及分享:
- 騷年你的屏幕適配方式該升級(jí)了!(一)-今日頭條適配方案
- 騷年你的屏幕適配方式該升級(jí)了!(二)-SmallestWidth 限定符適配方案
- 今日頭條屏幕適配方案終極版正式發(fā)布!
- 為什么說(shuō) AndroidAutoLayout 的設(shè)計(jì)有問(wèn)題
前言
我在前面兩篇文章中詳細(xì)介紹了 今日頭條適配方案 和 SmallestWidth 限定符適配方案 的原理,并驗(yàn)證了它們的可行性,以及總結(jié)了它們各自的優(yōu)缺點(diǎn),可以說(shuō)這兩個(gè)方案都是目前比較優(yōu)秀、比較主流的 Android 屏幕適配方案,而且它們都已經(jīng)擁有了一定的用戶基數(shù)
但是對(duì)于一些才接觸這兩個(gè)方案的朋友,肯定或多或少還是不知道如何選擇這兩個(gè)方案,我雖然在之前的文章中給出了它們各自的優(yōu)缺點(diǎn),但是并沒(méi)有用統(tǒng)一的標(biāo)準(zhǔn)對(duì)它們進(jìn)行更細(xì)致的對(duì)比,所以也就沒(méi)辦法更形象的體現(xiàn)它們的優(yōu)劣,那下面我就用統(tǒng)一的標(biāo)準(zhǔn)對(duì)它們進(jìn)行對(duì)比,看看它們的對(duì)比情況
方案對(duì)比
我始終堅(jiān)定地認(rèn)為在這兩個(gè)方案中,并不能以單個(gè)標(biāo)準(zhǔn)就能評(píng)判出誰(shuí)一定比誰(shuí)好,因?yàn)樗鼈兌加懈髯缘膬?yōu)缺點(diǎn),都不是完美的,從更客觀的角度來(lái)看,它們誰(shuí)都不能成為最好的那個(gè),只有可能明確了它們各自的優(yōu)缺點(diǎn),知道在它們的優(yōu)缺點(diǎn)里什么是我能接受的,什么是我不能接受的,是否能為了某些優(yōu)點(diǎn)做出某些妥協(xié),從而選擇出一個(gè)最適合自己項(xiàng)目的屏幕適配方案
單純的爭(zhēng)論誰(shuí)是最好的 Android 屏幕適配方案沒(méi)有任何意義,每個(gè)人的需求不一樣,站的角度不一樣,評(píng)判標(biāo)準(zhǔn)也不一樣,你能接受的東西他不一定能接受,你覺(jué)得不可接受的東西他卻覺(jué)得可以接受,你有你的理由,他有他的理由,想讓一個(gè)觀點(diǎn)讓所有人都能接受太難了!所以我在這里只是列出它們的對(duì)比項(xiàng)和對(duì)比結(jié)果,盡可能的做到客觀,最后的選擇結(jié)果請(qǐng)自行決定,如果還有什么遺漏的對(duì)比項(xiàng),請(qǐng)補(bǔ)充!
| 對(duì)比項(xiàng)目 | 對(duì)比對(duì)象 A | 對(duì)比結(jié)果 | 對(duì)比對(duì)象 B |
|---|---|---|---|
| 適配效果(越高越好) | 今日頭條適配方案 | ≈ | SW 限定符適配方案(在未覆蓋的機(jī)型上會(huì)存在一定的誤差) |
| 穩(wěn)定性(越高越好) | 今日頭條適配方案 | < | SW 限定符適配方案 |
| 靈活性(越高越好) | 今日頭條適配方案 | > | SW 限定符適配方案 |
| 擴(kuò)展性(越高越好) | 今日頭條適配方案 | > | SW 限定符適配方案 |
| 侵入性(越低越好) | 今日頭條適配方案 | < | SW 限定符適配方案 |
| 使用成本(越低越好) | 今日頭條適配方案 | < | SW 限定符適配方案 |
| 維護(hù)成本(越低越好) | 今日頭條適配方案 | < | SW 限定符適配方案 |
| 性能損耗 | 今日頭條適配方案沒(méi)有性能損耗 | = | SW 限定符適配方案沒(méi)有性能損耗 |
| 副作用 | 今日頭條適配方案會(huì)影響一些三方庫(kù)和系統(tǒng)控件 | ≈ | SW 限定符適配方案會(huì)影響 App 的體積 |
可以看到 SmallestWidth 限定符適配方案 和 今日頭條適配方案 的適配效果其實(shí)都是差不多的,我在前面的文章中也通過(guò)公式計(jì)算過(guò)它們的精確度,SmallestWidth 限定符適配方案 運(yùn)行在未覆蓋的機(jī)型上雖然也可以適配,但是卻會(huì)出現(xiàn)一定的誤差,所以 今日頭條適配方案 的適配精確度確實(shí)要比 SmallestWidth 限定符適配方案 略高的,不過(guò)只要 SmallestWidth 限定符適配方案 合理的分配資源文件,適配效果的差距應(yīng)該也不大
SmallestWidth 限定符適配方案 主打的是穩(wěn)定性,在運(yùn)行過(guò)程中極少會(huì)出現(xiàn)安全隱患,適配范圍也可控,不會(huì)產(chǎn)生其他未知的影響,而 今日頭條適配方案 主打的是降低開(kāi)發(fā)成本、提高開(kāi)發(fā)效率,使用上更靈活,也能滿足更多的擴(kuò)展需求,簡(jiǎn)單一句話概括就是,這兩兄弟,一個(gè)求穩(wěn),一個(gè)求快,好了,我就介紹這么多了,自己選擇吧!
AndroidAutoSize

由來(lái)
下面就開(kāi)始介紹我根據(jù) 今日頭條屏幕適配方案 優(yōu)化的屏幕適配框架 AndroidAutoSize,大家千萬(wàn)不要認(rèn)為,我推出的屏幕適配框架 AndroidAutoSize 是根據(jù) 今日頭條屏幕適配方案 優(yōu)化的,我本人就一定支持 今日頭條屏幕適配方案 是最好的 Android 屏幕適配方案這個(gè)觀點(diǎn),它確實(shí)很優(yōu)秀,但同樣也有很多不足,我最真實(shí)的觀點(diǎn)在上面就已經(jīng)表述咯,至于我為什么要根據(jù) 今日頭條屏幕適配方案 再封裝一個(gè)屏幕適配框架,無(wú)外乎就以下幾點(diǎn)原因:
SmallestWidth 限定符適配方案 已經(jīng)有多個(gè)優(yōu)秀的開(kāi)源解決方案了,它們已經(jīng)能滿足我們?nèi)粘i_(kāi)發(fā)中的所有需求
今日頭條 官方技術(shù)團(tuán)隊(duì)只公布了 今日頭條屏幕適配方案 的 文章 以及核心代碼,但并沒(méi)有在 Github 上創(chuàng)建公開(kāi)的倉(cāng)庫(kù),一個(gè)新的方案必定要有一個(gè)成長(zhǎng)迭代的過(guò)程,在此期間,一定需要一個(gè)可以把所有使用者聚集起來(lái)的公共社區(qū),可以讓所有使用該方案的使用者在上面交流,大家一起總結(jié)、一起填坑,這樣才能讓該方案更成熟穩(wěn)定,這就是開(kāi)源的力量
今日頭條 官方技術(shù)團(tuán)隊(duì)公布的核心代碼并不能滿足我的所有需求,已經(jīng)開(kāi)源的其他基于 今日頭條屏幕適配方案 的開(kāi)源項(xiàng)目以及解決方案也不能滿足我的所有需求,而我有更好的實(shí)現(xiàn)想法
MVPArms 需要一個(gè)適配效果還不錯(cuò)并且切換維護(hù)成本也比較低的屏幕適配框架,以幫助使用者用較低的成本、工作量將已經(jīng)停止維護(hù)的 AndroidAutoLayout 快速替換掉
我建議大家都可以去實(shí)際體驗(yàn)一下 今日頭條屏幕適配方案 和 SmallestWidth 限定符適配方案,感受下它們的異同,我給的建議是,可以在項(xiàng)目中先使用 今日頭條屏幕適配方案,感受下它的使用方式以及適配效果,今日頭條屏幕適配方案 的侵入性非常低,如果在使用過(guò)程中遇到什么不能解決的問(wèn)題,馬上可以切換為其他的屏幕適配方案,在切換的過(guò)程中也花費(fèi)不了多少工作量,試錯(cuò)成本非常低
但如果你在項(xiàng)目中先使用 SmallestWidth 限定符適配方案,之后在使用的過(guò)程中再遇到什么不能解決的問(wèn)題,這時(shí)想切換為其他的屏幕適配方案,這工作量可就大了,每個(gè) Layout 文件都含有大量的 dimens 引用,改起來(lái)這工作量得有多大,想想都覺(jué)得后怕,這就是侵入性太高導(dǎo)致的最致命的問(wèn)題
如果想體驗(yàn) 今日頭條屏幕適配方案,千萬(wàn)不要錯(cuò)過(guò) AndroidAutoSize 哦!僅需一步即可接入項(xiàng)目,下面是 AndroidAutoSize 的地址:
Github : 您的 Star 是我堅(jiān)持的動(dòng)力 ?
與今日頭條屏幕適配方案的關(guān)系
AndroidAutoSize 與 今日頭條屏幕適配方案 的關(guān)系,相當(dāng)于汽車和發(fā)動(dòng)機(jī)的關(guān)系,今日頭條屏幕適配方案 官方公布的代碼,只實(shí)現(xiàn)了修改系統(tǒng) density 的相關(guān)邏輯,這的確在屏幕適配中起到了最關(guān)鍵的作用,但這還遠(yuǎn)遠(yuǎn)還不夠
要想讓使用者能夠更傻瓜式的使用該方案,并且能夠應(yīng)對(duì)日常開(kāi)發(fā)中的所有復(fù)雜需求,那在架構(gòu)框架時(shí),還需要考慮 API 的易用性以及合理性、框架的擴(kuò)展性以及靈活性、功能的全面性、注釋和文檔的易讀性等多個(gè)方面的問(wèn)題
于是我?guī)е业倪@些標(biāo)準(zhǔn)在網(wǎng)上搜尋了很久,發(fā)現(xiàn)并沒(méi)有任何一個(gè)開(kāi)源框架或解決方案能夠達(dá)到我的所有標(biāo)準(zhǔn),它們大多數(shù)還只是停留在將 今日頭條屏幕適配方案 封裝成工具類來(lái)引入項(xiàng)目的階段,這樣在功能的擴(kuò)展上有限制,并且對(duì)用戶的使用體驗(yàn)也不好,而我想做的是一個(gè)全面性的產(chǎn)品級(jí)屏幕適配框架,這離我最初的構(gòu)想,差距還非常大,于是我只好自己動(dòng)手,將我的所有思想實(shí)現(xiàn),這才有了 AndroidAutoSize
寫(xiě)完 AndroidAutoSize 框架后,因?yàn)閷?duì) 今日頭條屏幕適配方案 有了更加深入的理解,所以才寫(xiě)了 騷年你的屏幕適配方式該升級(jí)了!(一)-今日頭條適配方案,以幫助大家更清晰的理解 今日頭條屏幕適配方案
與 AndroidAutoLayout 的關(guān)系
AndroidAutoSize 因?yàn)槊趾?鴻神 的 AndroidAutoLayout 非常相似,并且在填寫(xiě)設(shè)計(jì)圖尺寸的方式上也極為相似,再加上我寫(xiě)的屏幕適配系列的文章也發(fā)布在了 鴻神 的公眾號(hào)上,所以很多人以為 AndroidAutoSize 是 鴻神 寫(xiě)的 AndroidAutoLayout 的升級(jí)版,這里我哭笑不得 ??,我只好在這里說(shuō)一句,大家好,我叫 JessYan,的確可以理解為 AndroidAutoSize 是 AndroidAutoLayout 的升級(jí)版,但是它是我寫(xiě)的,關(guān)注一波唄
但 AndroidAutoSize 和 AndroidAutoLayout 的原理,卻天差地別,比如 AndroidAutoLayout 只能使用 px 作為布局單位,而 AndroidAutoSize 恰好相反,在布局中 dp、sp、pt、in、mm 所有的單位都能支持,唯獨(dú)不支持 px,但這也意味著 AndroidAutoSize 和 AndroidAutoLayout 在項(xiàng)目中可以共存,互不影響,所以使用 AndroidAutoLayout 的老項(xiàng)目也可以放心的引入 AndroidAutoSize,慢慢的完成屏幕適配框架的切換
之所以將框架取名為 AndroidAutoSize,第一,是想致敬 AndroidAutoLayout 對(duì) Android 屏幕適配領(lǐng)域的貢獻(xiàn),第二,也想成為在 Android 屏幕適配領(lǐng)域有重要影響力的框架
結(jié)構(gòu)
我在上面就已經(jīng)說(shuō)了很多開(kāi)源框架以及解決方案,只是把 今日頭條屏幕適配方案 簡(jiǎn)單的封裝成一個(gè)工具類然后引入項(xiàng)目,這時(shí)很多人就會(huì)說(shuō)了 今日頭條屏幕適配方案 官方公布的全部代碼都只有 30 行不到,你不把它封裝成工具類,那封裝成什么?該怎么封裝?下面就來(lái)看看 AndroidAutoSize 的整體結(jié)構(gòu)
├── external
│ ├── ExternalAdaptInfo.java
│ ├── ExternalAdaptManager.java
│── internal
│ ├── CancelAdapt.java
│ ├── CustomAdapt.java
│── unit
│ ├── Subunits.java
│ ├── UnitsManager.java
│── utils
│ ├── AutoSizeUtils.java
│ ├── LogUtils.java
│ ├── Preconditions.java
│ ├── ScreenUtils.java
├── ActivityLifecycleCallbacksImpl.java
├── AutoAdaptStrategy.java
├── AutoSize.java
├── AutoSizeConfig.java
├── DefaultAutoAdaptStrategy.java
├── DisplayMetricsInfo.java
├── FragmentLifecycleCallbacksImpl.java
├── InitProvider.java
AndroidAutoSize 根據(jù) 今日頭條屏幕適配方案 官方公布的 30 行不到的代碼,經(jīng)過(guò)不斷的優(yōu)化和擴(kuò)展,發(fā)展成了現(xiàn)在擁有 18 個(gè)類文件,上千行代碼的全面性屏幕適配框架,在迭代的過(guò)程中完善和優(yōu)化了很多功能,相比 今日頭條屏幕適配方案 官方公布的原始代碼,AndroidAutoSize 更加穩(wěn)定、更加易用、更加強(qiáng)大,歡迎閱讀源碼,注釋非常詳細(xì)哦!
功能介紹
AndroidAutoSize 在使用上非常簡(jiǎn)單,只需要填寫(xiě)設(shè)計(jì)圖尺寸這一步即可接入項(xiàng)目,但需要注意的是,AndroidAutoSize 有兩種類型的布局單位可以選擇,一個(gè)是 主單位 (dp、sp),一個(gè)是 副單位 (pt、in、mm),兩種單位面向的應(yīng)用場(chǎng)景都有不同,也都有各自的優(yōu)缺點(diǎn)
主單位: 使用 dp、sp 為單位進(jìn)行布局,侵入性最低,會(huì)影響其他三方庫(kù)頁(yè)面、三方庫(kù)控件以及系統(tǒng)控件的布局效果,但 AndroidAutoSize 也通過(guò)這個(gè)特性,使用 ExternalAdaptManager 實(shí)現(xiàn)了在不修改三方庫(kù)源碼的情況下適配三方庫(kù)的功能
副單位: 使用 pt、in、mm 為單位進(jìn)行布局,侵入性高,對(duì)老項(xiàng)目的支持比較好,不會(huì)影響其他三方庫(kù)頁(yè)面、三方庫(kù)控件以及系統(tǒng)控件的布局效果,可以徹底的屏蔽修改 density 所造成的所有未知和已知問(wèn)題,但這樣 AndroidAutoSize 也就無(wú)法對(duì)三方庫(kù)進(jìn)行適配
大家可以根據(jù)自己的應(yīng)用場(chǎng)景在 主單位 和 副單位 中選擇一個(gè)作為布局單位,建議想引入老項(xiàng)目并且注重穩(wěn)定性的人群使用 副單位,只是想試試本框架,隨時(shí)可能切換為其他屏幕適配方案的人群使用 主單位
其實(shí) AndroidAutoSize 可以同時(shí)支持 主單位 和 副單位,但 AndroidAutoSize 可以同時(shí)支持 主單位 和 副單位 的目的,只是為了讓使用者可以在 主單位 和 副單位 之間靈活切換,因?yàn)榍袚Q單位的工作量可能非常巨大,不能立即完成,但領(lǐng)導(dǎo)又要求馬上打包上線,這時(shí)就可以起到一個(gè)很好的過(guò)渡作用
主單位
主單位 的 Demo 在 demo
基本使用
將 AndroidAutoSize 引入項(xiàng)目后,只要在 app 的 AndroidManifest.xml 中填寫(xiě)上設(shè)計(jì)圖尺寸,無(wú)需其他過(guò)多配置 (如果你沒(méi)有其他自定義需求的話),AndroidAutoSize 即可自動(dòng)運(yùn)行,像下面這樣??
<manifest>
<application>
<meta-data
android:name="design_width_in_dp"
android:value="360"/>
<meta-data
android:name="design_height_in_dp"
android:value="640"/>
</application>
</manifest>
在使用主單位時(shí),design_width_in_dp 和 design_height_in_dp 的單位必須是 dp,如果設(shè)計(jì)師給你的設(shè)計(jì)圖,只標(biāo)注了 px 尺寸 (現(xiàn)在已經(jīng)有很多 UI 工具可以自動(dòng)標(biāo)注 dp 尺寸了),那請(qǐng)自行根據(jù)公式 dp = px / (DPI / 160) 將 px 尺寸轉(zhuǎn)換為 dp 尺寸,如果你不知道 DPI 是多少?那請(qǐng)以自己測(cè)試機(jī)的 DPI 為準(zhǔn),如果連怎么得到設(shè)備的 DPI 都不知道?百度吧好伐,如果你實(shí)在找不到設(shè)備的 DPI 那就直接將 px 尺寸除以 3 或者 2 也是可以的
如果你只是想使用 AndroidAutoSize 的基礎(chǔ)功能,AndroidAutoSize 的使用方法在這里就結(jié)束了,只需要上面這一步,即可幫助你以最簡(jiǎn)單的方式接入 AndroidAutoSize,但是作為一個(gè)全面性的屏幕適配框架,在保證基礎(chǔ)功能的簡(jiǎn)易性的同時(shí),也必須保證復(fù)雜的需求也能在框架內(nèi)被解決,從而達(dá)到一個(gè)小閉環(huán),所以下面介紹的內(nèi)容全是前人踩坑踩出來(lái)的一些必備功能,如果你沒(méi)這個(gè)需求,或者覺(jué)得麻煩,可以按需查看或者跳過(guò),下面的內(nèi)容建議和 Demo 配合起來(lái)閱讀,效果更佳
注意事項(xiàng)
- 你在 AndroidManifest.xml 中怎么把設(shè)計(jì)圖的 px 尺寸轉(zhuǎn)換為 dp 尺寸,那在布局時(shí),每個(gè)控件的大小也需要以同樣的方式將設(shè)計(jì)圖上標(biāo)注的 px 尺寸轉(zhuǎn)換為 dp 尺寸,千萬(wàn)不要在 AndroidManifest.xml 中填寫(xiě)的是 dp 尺寸,卻在布局中繼續(xù)填寫(xiě)設(shè)計(jì)圖上標(biāo)注的 px 尺寸
-
design_width_in_dp和design_height_in_dp雖然都需要填寫(xiě),但是 AndroidAutoSize 只會(huì)將高度和寬度其中的一個(gè)作為基準(zhǔn)進(jìn)行適配,一方作為基準(zhǔn),另一方就會(huì)變?yōu)閭溆茫J(rèn)以寬度為基準(zhǔn)進(jìn)行適配,可以通過(guò) AutoSizeConfig#setBaseOnWidth(Boolean) 不停的切換,這意味著最后運(yùn)行到設(shè)備上的布局效果,在高度和寬度中只有一方可以和設(shè)計(jì)圖上一模一樣,另外一方會(huì)和設(shè)計(jì)圖出現(xiàn)偏差,為什么不像 AndroidAutoLayout 一樣,高和寬都以設(shè)計(jì)圖的效果等比例完美呈現(xiàn)呢?這也很簡(jiǎn)單,你無(wú)法保證所有設(shè)備的高寬比例都和你設(shè)計(jì)圖上的高寬比例一致,特別是在現(xiàn)在全面屏全面推出的情況下,如果這里不這樣做的話,當(dāng)你的項(xiàng)目運(yùn)行在與設(shè)計(jì)圖高寬比例不一致的設(shè)備上時(shí),布局會(huì)出現(xiàn)嚴(yán)重的變形,這個(gè)幾率非常大,詳情請(qǐng)看 這里
自動(dòng)運(yùn)行是如何做到的?
很多人有疑惑,為什么使用者只需要在 AndroidManifest.xml 中填寫(xiě)一下 meta-data 標(biāo)簽,其他什么都不做,AndroidAutoSize 就能自動(dòng)運(yùn)行,并在 App 啟動(dòng)時(shí)自動(dòng)解析 AndroidManifest.xml 中填寫(xiě)的設(shè)計(jì)圖尺寸,這里很多人不敢相信,問(wèn)我真的只需要填寫(xiě)下設(shè)計(jì)圖尺寸框架就可以正常運(yùn)行嗎?難道使用了什么 黑科技?
其實(shí)這里并沒(méi)有用到什么 黑科技,原理反而非常簡(jiǎn)單,只需要聲明一個(gè) ContentProvider,在它的 onCreate 方法中啟動(dòng)框架即可,在 App 啟動(dòng)時(shí),系統(tǒng)會(huì)在 App 的主進(jìn)程中自動(dòng)實(shí)例化你聲明的這個(gè) ContentProvider,并調(diào)用它的 onCreate 方法,執(zhí)行時(shí)機(jī)比 Application#onCreate 還靠前,可以做一些初始化的工作,get 到了嗎?
這里需要注意的是,如果你的項(xiàng)目擁有多進(jìn)程,系統(tǒng)只會(huì)在主進(jìn)程中實(shí)例化一個(gè)你聲明的 ContentProvider,并不會(huì)在其他非主進(jìn)程中實(shí)例化 ContentProvider,如果在當(dāng)前進(jìn)程中 ContentProvider 沒(méi)有被實(shí)例化,那 ContentProvider#onCreate 就不會(huì)被調(diào)用,你的初始化代碼在當(dāng)前進(jìn)程中也就不會(huì)執(zhí)行,這時(shí)就需要在 Application#onCreate 中調(diào)用下 ContentProvider#query 執(zhí)行一下查詢操作,這時(shí) ContentProvider 就會(huì)在當(dāng)前進(jìn)程中實(shí)例化 (每個(gè)進(jìn)程中只會(huì)保證有一個(gè)實(shí)例),所以應(yīng)用到框架中就是,如果你需要在多個(gè)進(jìn)程中都進(jìn)行屏幕適配,那就需要在 Application#onCreate 中調(diào)用 AutoSize#initCompatMultiProcess 方法
進(jìn)階使用
雖然 AndroidAutoSize 不需要其他過(guò)多的配置,只需要在 AndroidManifest.xml 中填寫(xiě)下設(shè)計(jì)圖尺寸就能正常運(yùn)行,但 AndroidAutoSize 還是為大家準(zhǔn)備了很多可配置選項(xiàng),盡最大可能滿足大家日常開(kāi)發(fā)中的所有擴(kuò)展需求
所有的全局配置選項(xiàng)在 Demo 中都有介紹,每個(gè) API 中也都有詳細(xì)的注釋,在這里就不過(guò)多介紹了
自定義 Activity
在 AndroidManifest.xml 中填寫(xiě)的設(shè)計(jì)圖尺寸,是整個(gè)項(xiàng)目的全局設(shè)計(jì)圖尺寸,但是如果某些 Activity 頁(yè)面由于某些原因,設(shè)計(jì)師單獨(dú)出圖,這個(gè)頁(yè)面的設(shè)計(jì)圖尺寸和在 AndroidManifest.xml 中填寫(xiě)的設(shè)計(jì)圖尺寸不一樣該怎么辦呢?不要急,AndroidAutoSize 已經(jīng)為你考慮好了,讓這個(gè)頁(yè)面的 Activity 實(shí)現(xiàn) CustomAdapt 接口即可實(shí)現(xiàn)你的需求,CustomAdapt 接口的第一個(gè)方法可以修改當(dāng)前頁(yè)面的設(shè)計(jì)圖尺寸,第二個(gè)方法可以切換當(dāng)前頁(yè)面的適配基準(zhǔn),下面的注釋都解釋的很清楚
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt {
/**
* 是否按照寬度進(jìn)行等比例適配 (為了保證在高寬比不同的屏幕上也能正常適配, 所以只能在寬度和高度之中選擇一個(gè)作為基準(zhǔn)進(jìn)行適配)
*
* @return {@code true} 為按照寬度進(jìn)行適配, {@code false} 為按照高度進(jìn)行適配
*/
@Override
public boolean isBaseOnWidth() {
return false;
}
/**
* 這里使用 iPhone 的設(shè)計(jì)圖, iPhone 的設(shè)計(jì)圖尺寸為 750px * 1334px, 高換算成 dp 為 667 (1334px / 2 = 667dp)
* <p>
* 返回設(shè)計(jì)圖上的設(shè)計(jì)尺寸, 單位 dp
* {@link #getSizeInDp} 須配合 {@link #isBaseOnWidth()} 使用, 規(guī)則如下:
* 如果 {@link #isBaseOnWidth()} 返回 {@code true}, {@link #getSizeInDp} 則應(yīng)該返回設(shè)計(jì)圖的總寬度
* 如果 {@link #isBaseOnWidth()} 返回 {@code false}, {@link #getSizeInDp} 則應(yīng)該返回設(shè)計(jì)圖的總高度
* 如果您不需要自定義設(shè)計(jì)圖上的設(shè)計(jì)尺寸, 想繼續(xù)使用在 AndroidManifest 中填寫(xiě)的設(shè)計(jì)圖尺寸, {@link #getSizeInDp} 則返回 {@code 0}
*
* @return 設(shè)計(jì)圖上的設(shè)計(jì)尺寸, 單位 dp
*/
@Override
public float getSizeInDp() {
return 667;
}
}
如果某個(gè) Activity 想放棄適配,讓這個(gè) Activity 實(shí)現(xiàn) CancelAdapt 接口即可,比如修改 density 影響到了老項(xiàng)目中的某些 Activity 頁(yè)面的布局效果,這時(shí)就可以讓這個(gè) Activity 實(shí)現(xiàn) CancelAdapt 接口
public class CancelAdaptActivity extends AppCompatActivity implements CancelAdapt {
}
自定義 Fragment
Fragment 的自定義方式和 Activity 是一樣的,只不過(guò)在使用前需要先在 App 初始化時(shí)開(kāi)啟對(duì) Fragment 的支持
AutoSizeConfig.getInstance().setCustomFragment(true);
實(shí)現(xiàn) CustomAdapt
public class CustomAdaptFragment extends Fragment implements CustomAdapt {
@Override
public boolean isBaseOnWidth() {
return false;
}
@Override
public float getSizeInDp() {
return 667;
}
}
實(shí)現(xiàn) CancelAdapt
public class CancelAdaptFragment extends Fragment implements CancelAdapt {
}
適配三方庫(kù)頁(yè)面
在使用主單位時(shí)可以使用 ExternalAdaptManager 來(lái)實(shí)現(xiàn)在不修改三方庫(kù)源碼的情況下,適配三方庫(kù)的所有頁(yè)面 (Activity、Fragment)
由于 AndroidAutoSize 要求需要自定義適配參數(shù)或取消適配的頁(yè)面必須實(shí)現(xiàn) CustomAdapt、CancelAdapt,這時(shí)問(wèn)題就來(lái)了,三方庫(kù)是通過(guò)遠(yuǎn)程依賴的,我們無(wú)法修改它的源碼,這時(shí)我們?cè)趺醋屓綆?kù)的頁(yè)面也能實(shí)現(xiàn)自定義適配參數(shù)或取消適配呢?別急,這個(gè)需求 AndroidAutoSize 也已經(jīng)為你考慮好了,當(dāng)然不會(huì)讓你將三方庫(kù)下載到本地然后改源碼!
通過(guò) ExternalAdaptManager#addExternalAdaptInfoOfActivity(Class, ExternalAdaptInfo) 將需要自定義的類和自定義適配參數(shù)添加進(jìn)方法即可替代實(shí)現(xiàn) CustomAdapt 的方式,這里 展示了使用方式,以及詳細(xì)的注釋
通過(guò) ExternalAdaptManager#addCancelAdaptOfActivity(Class) 將需要取消適配的類添加進(jìn)方法即可替代實(shí)現(xiàn) CancelAdapt 的方式,這里 也展示了使用方式,以及詳細(xì)的注釋
需要注意的是 ExternalAdaptManager 的方法雖然可以添加任何類,但是只能支持 Activity、Fragment,并且 ExternalAdaptManager 是支持鏈?zhǔn)秸{(diào)用的,以便于持續(xù)添加多個(gè)頁(yè)面
當(dāng)然 ExternalAdaptManager 不僅可以對(duì)三方庫(kù)的頁(yè)面使用,也可以讓自己項(xiàng)目中的 Activity、Fragment 不用實(shí)現(xiàn) CustomAdapt、CancelAdapt 即可達(dá)到自定義適配參數(shù)和取消適配的功能
副單位
前面已經(jīng)介紹了 副單位 的應(yīng)用場(chǎng)景,這里就直接介紹 副單位 如何使用,副單位 的 Demo 在 demo-subunits
基本使用
首先和 主單位 一樣也需要先在 app 的 AndroidManifest.xml 中填寫(xiě)上設(shè)計(jì)圖尺寸,但和 主單位 不一樣的是,當(dāng)在使用 副單位 時(shí) design_width_in_dp 和 design_height_in_dp 的單位不需要一定是 dp,可以直接填寫(xiě)設(shè)計(jì)圖的 px 尺寸,在布局文件中每個(gè)控件的大小也可以直接填寫(xiě)設(shè)計(jì)圖上標(biāo)注的 px 尺寸,無(wú)需再將 px 轉(zhuǎn)換為 dp,這是 副單位的 特性之一,可以幫助大家提高開(kāi)發(fā)效率
<manifest>
<application>
<meta-data
android:name="design_width_in_dp"
android:value="1080"/>
<meta-data
android:name="design_height_in_dp"
android:value="1920"/>
</application>
</manifest>
由于 AndroidAutoSize 提供了 pt、in、mm 三種類型的 副單位 供使用者選擇,所以在使用 副單位 時(shí),還需要在 APP 初始化時(shí),通過(guò) UnitsManager#setSupportSubunits(Subunits) 方法選擇一個(gè)你喜歡的副單位,然后在布局文件中使用這個(gè)副單位進(jìn)行布局,三種類型的副單位,其實(shí)效果都是一樣,大家按喜歡的名字選擇即可
由于使用副單位是為了徹底屏蔽修改 density 所造成的對(duì)三方庫(kù)頁(yè)面、三方庫(kù)控件以及系統(tǒng)控件的布局效果的影響,所以在使用副單位時(shí)建議調(diào)用 UnitsManager#setSupportDP(false) 和 UnitsManager#setSupportSP(false),關(guān)閉 AndroidAutoSize 對(duì) dp 和 sp 的支持,AndroidAutoSize 為什么不在使用 副單位 時(shí)默認(rèn)關(guān)閉對(duì) dp、sp 的支持?因?yàn)樵试S同時(shí)支持 主單位 和 副單位 可以幫助使用者在 主單位 和 副單位 之間切換時(shí)更好的過(guò)渡,這點(diǎn)在前面就已經(jīng)提到過(guò)
UnitsManager 的詳細(xì)使用方法,在 demo-subunits 中都有展示,注釋也十分詳細(xì)
自定義 Activity 和 Fragment
在使用 副單位 時(shí)自定義 Activity 和 Fragment 的方式是和 主單位 是一樣的,這里就不再過(guò)多介紹了
適配三方庫(kù)頁(yè)面
如果你的項(xiàng)目在使用 副單位 并且關(guān)閉了對(duì) 主單位 (dp、sp) 的支持,這時(shí) ExternalAdaptManager 對(duì)三方庫(kù)的頁(yè)面是不起作用的,只對(duì)自己項(xiàng)目中的頁(yè)面起作用,除非三方庫(kù)的頁(yè)面也使用了副單位 (pt、in、mm) 進(jìn)行布局
其實(shí) 副單位 之所以能徹底屏蔽修改 density 所造成的對(duì)三方庫(kù)頁(yè)面、三方庫(kù)控件以及系統(tǒng)控件的布局效果的影響,就是因?yàn)槿綆?kù)頁(yè)面、三方庫(kù)控件以及系統(tǒng)控件基本上使用的都是 dp、sp 進(jìn)行布局,所以只要 AndroidAutoSize 關(guān)閉了對(duì) dp、sp 的支持,轉(zhuǎn)而使用 副單位 進(jìn)行布局,就能徹底屏蔽修改 density 所造成的對(duì)三方庫(kù)頁(yè)面、三方庫(kù)控件以及系統(tǒng)控件的布局效果的影響
但這也同樣意味著使用 副單位 就不能適配三方庫(kù)的頁(yè)面了,ExternalAdaptManager 也就對(duì)三方庫(kù)的頁(yè)面不起作用了
布局實(shí)時(shí)預(yù)覽
在開(kāi)發(fā)階段布局時(shí)的實(shí)時(shí)預(yù)覽是一個(gè)很重要的環(huán)節(jié),很多情況下 Android Studio 提供的默認(rèn)預(yù)覽設(shè)備并不能完全展示我們的設(shè)計(jì)圖,所以我們就需要自己創(chuàng)建模擬設(shè)備,dp、pt、in、mm 這四種單位的模擬設(shè)備創(chuàng)建方法請(qǐng)看 這里
總結(jié)
AndroidAutoSize 在經(jīng)歷了 240+ commit、60+ issues、6 個(gè)版本 的洗禮后,逐漸的穩(wěn)定了下來(lái),已經(jīng)在上個(gè)星期發(fā)布了首個(gè)正式版,在這里要感謝將 AndroidAutoSize 接入到自己項(xiàng)目中的上千個(gè)使用者,感謝他們的信賴,AndroidAutoSize 創(chuàng)建的初衷就是為了讓所有使用 今日頭條屏幕適配方案 的使用者能有一個(gè)可以一起交流、溝通的聚集地,所以后面也會(huì)持續(xù)的收集并解決 今日頭條屏幕適配方案的常見(jiàn)問(wèn)題,讓 今日頭條屏幕適配方案 變得更加成熟、穩(wěn)定
至此本系列的第三篇文章也就完結(jié)了,這也預(yù)示著這個(gè)系列連載的終結(jié),這篇文章建議結(jié)合系列的第一篇文章 騷年你的屏幕適配方式該升級(jí)了!(一)-今日頭條適配方案 一起看,這樣可以對(duì) 今日頭條屏幕適配方案 有一個(gè)更深入的理解,如果你能將整個(gè)系列的文章都全部認(rèn)真看完,那你對(duì) Android 屏幕適配領(lǐng)域的相關(guān)知識(shí)絕對(duì)會(huì)有一個(gè)飛速的提升!
當(dāng)你的項(xiàng)目需要切換某個(gè)框架時(shí),你會(huì)怎么去考察、分析、對(duì)比現(xiàn)有的開(kāi)源方案,并有足夠的理由去選擇或優(yōu)化一個(gè)最適合自己項(xiàng)目的方案呢?其實(shí)整個(gè)系列文章可以看作是我怎么去選擇同類型開(kāi)源方案的過(guò)程,你以后當(dāng)遇到同樣的選擇也可以參照我的思維方式去處理,當(dāng)然如果以后面試官問(wèn)到你屏幕適配相關(guān)的問(wèn)題,你能將我如何選擇、分析、對(duì)比已有方案的過(guò)程以及文章中的核心知識(shí)點(diǎn)告訴給面試官,那肯定比你直接說(shuō)一句我使用的是某某開(kāi)源庫(kù)有價(jià)值得多
以下是 騷年你的屏幕適配方式該升級(jí)了! 系列文章,歡迎轉(zhuǎn)發(fā)以及分享: