在 2019 年的 Google I/O 和 Apple WWDC 上踩寇,新露面的 Android 10 和 iOS 13 都宣布將支持 Dark Theme 也就是我們常說(shuō)的暗黑模式啄清,并提供相關(guān) API 供開(kāi)發(fā)者適配。
那么俺孙,為什么我們需要暗黑模式辣卒?暗黑模式到底有什么好處?Android 開(kāi)發(fā)者該如何適配暗黑模式呢睛榄?今天這篇文章就告訴你荣茫。
Why we need Dark Theme?
暗色主題的 App 比比皆是计露,但是讓 Android 和 iOS 從系統(tǒng)層級(jí)支持暗黑模式還是頭一次博脑。也許是用戶的呼聲也許是工業(yè)的推動(dòng)憎乙,發(fā)展得益于進(jìn)步和反饋,暗黑模式就這樣來(lái)到了你我的手機(jī)上叉趣。
以上這張圖截選自 Android 官方文檔泞边,上面提出了 Dark Theme 的三點(diǎn)好處:
可以幫助我們節(jié)省更多的電量
為弱視以及對(duì)強(qiáng)光敏感的用戶提高可視性
讓所有人都可以在光線較暗的環(huán)境中更輕松地使用設(shè)備
這得益于 OLED 屏幕的發(fā)展,與 LCD 不同 OLED 能夠自發(fā)光疗杉,每個(gè)像素點(diǎn)都能發(fā)出紅綠藍(lán)三色光阵谚,而 LCD 則通過(guò)其背光層穿透有顏色的薄膜來(lái)發(fā)出不同的光。這樣在暗黑模式下烟具,OLED 就具有天生的優(yōu)勢(shì)梢什,只需要關(guān)閉黑色區(qū)域的顯示,就可以達(dá)到純黑效果朝聋,而 LCD 的背光層只能發(fā)射白光嗡午,所以在顯示黑色的時(shí)候,仍然會(huì)有部分光透過(guò)顏色薄膜冀痕,無(wú)法達(dá)到純黑效果荔睹,只能達(dá)到相對(duì)黑的效果狸演。
所以,在如今使用 OLED 屏幕的手機(jī)上面僻他,開(kāi)啟暗黑模式會(huì)大幅減少手機(jī)電量的消耗宵距。關(guān)于其中更詳細(xì)的作用原理以及好處,推薦閱讀來(lái)自中科院物理所公眾號(hào)的文章吨拗,點(diǎn)擊下方查看满哪。
為你的 Android App 適配暗黑模式
適配大概可以分為三部分工作:
為應(yīng)用內(nèi)的背景、文字丢胚、圖標(biāo)做適配
對(duì)在設(shè)備上顯示但并不直接控制的界面進(jìn)行適配翩瓜,例如通知、桌面組件
在應(yīng)用內(nèi)為用戶提供切換主題的開(kāi)關(guān)選項(xiàng)
適配的方式也分為三種:自動(dòng)適配携龟、自定義適配兔跌、使用 Material Design Components 進(jìn)行適配,為了方便說(shuō)明峡蟋,我這里寫(xiě)了一個(gè)實(shí)例代碼坟桅,在沒(méi)有開(kāi)啟適配前是這個(gè)樣子的。
自動(dòng)適配 Force Dark
Android 10 提供 Force Dark 功能蕊蝗。此功能可讓開(kāi)發(fā)者快速實(shí)現(xiàn)深色主題背景仅乓,只需要在 style.xml 中的應(yīng)用主題中添加這一行代碼 android:forceDarkAllowed="true" ,就可以完成自動(dòng)適配蓬戚。
如果您的應(yīng)用采用淺色主題背景夸楣,則 Force Dark 會(huì)分析應(yīng)用的每個(gè)視圖,并在相應(yīng)視圖在屏幕上顯示之前子漩,自動(dòng)應(yīng)用深色主題背景豫喧。當(dāng)然這里的適配工作全是系統(tǒng)自己做的,所以作為開(kāi)發(fā)者你需要進(jìn)行詳細(xì)的測(cè)試幢泼,確保沒(méi)有錯(cuò)誤的地方紧显。
從上面的截圖來(lái)看,自動(dòng)適配的效果很不錯(cuò)缕棵,關(guān)于自動(dòng)適配的原理孵班,這里有一篇文章對(duì)此進(jìn)行了詳細(xì)的說(shuō)明,文章地址在最后招驴。
自定義適配
自定義適配的關(guān)鍵在于篙程,避免一切硬編碼的顏色值,建立 light 别厘、night 兩份 colors虱饿,通過(guò)定義相同的名字,在不同模式下顯示不同的顏色。
1. 確保當(dāng)前 App 使用的主題繼承自 AppCompat 或 MaterialComponents郭厌,并將之前默認(rèn)的 Light 主題修改為 DayNight
2.為 Dark Mode 定義 colors
新建完成之后我們的 values 下會(huì)有兩份 colors 文件袋倔,工程結(jié)構(gòu)如下圖所示
3. 根據(jù)需求對(duì)不同模式下相同名字的顏色值做適配
這里推薦使用顏色本身的場(chǎng)景意義來(lái)命名,例如上圖中的 colorBackground 表示背景顏色折柠,colorOnError 表示在錯(cuò)誤狀態(tài)上宾娜,文字的顯示顏色,在控件需要顏色的地方扇售,直接通過(guò) @color/colorXXX 來(lái)使用
自定義適配完全可以達(dá)到任何我們想要的效果前塔,相比自動(dòng)適配,這里我對(duì)狀態(tài)欄承冰、錯(cuò)誤顏色以及強(qiáng)調(diào)色進(jìn)行了微調(diào)华弓。
使用 Material Design Components 進(jìn)行適配
Material Design Components 不僅僅包含了各式各樣的組件,還完善了 Material Design 的規(guī)范困乒,相比組件來(lái)說(shuō)更重要的是 MD 設(shè)計(jì)規(guī)范寂屏。
上圖為 Material Design 的官網(wǎng),在設(shè)計(jì)一覽中娜搂,詳細(xì)制定了各種規(guī)范迁霎,例如顏色系統(tǒng)該如何設(shè)計(jì)、陰影的原理和規(guī)范百宇、字體的規(guī)范考廉、圖標(biāo)該如何選擇、交互效果該怎樣設(shè)計(jì)等等携御。
我個(gè)人來(lái)說(shuō)是非常喜歡 Material Design 昌粤,之后會(huì)計(jì)劃在這個(gè)公眾號(hào)上面為大家詳細(xì)的介紹一下Material Design 到底是怎樣的,相信很多人都知道 Material Design 但真正讀過(guò)它的文檔啄刹,以及認(rèn)真了解過(guò)其設(shè)計(jì)原理的人涮坐,應(yīng)該寥寥無(wú)幾。
所以說(shuō)不是用了 Material Design 的組件就代表自己的 App 遵循了 Material Design 的設(shè)計(jì)規(guī)范鸵膏,也更別說(shuō)連這個(gè)規(guī)范都沒(méi)看過(guò)的人膊升,就一桿子打死說(shuō) Material Design 反人類(lèi)怎炊。
在 Material Design 官網(wǎng)顏色系統(tǒng)的設(shè)計(jì)中谭企,專(zhuān)門(mén)講解了關(guān)于 Dark theme 該如何設(shè)計(jì),之所以叫做 Dark theme评肆,所有的適配都是圍繞 theme 來(lái)進(jìn)行的债查。而上一節(jié)的自定義適配中,我們只是簡(jiǎn)單粗暴的通過(guò) colors 來(lái)適配瓜挽。
Material Design Components 中內(nèi)置了 12 種不同場(chǎng)景的顏色屬性盹廷,分別為主強(qiáng)調(diào)色、次強(qiáng)調(diào)色久橙,背景顏色俄占、表面顏色管怠、錯(cuò)誤顏色、以及字體和 icon 的顏色(以 on 開(kāi)頭的)缸榄。
所以在使用 Material Design Components 進(jìn)行適配的時(shí)候渤弛,我們需要定義兩種 theme,分別代表 light 和 night甚带,通過(guò)分別定義兩個(gè)主題中相同場(chǎng)景意義的顏色屬性來(lái)實(shí)現(xiàn)暗黑模式的切換她肯。而上一部分自定義適配則是,通過(guò)定義一份主題鹰贵,在同一主題下通過(guò)控制 light 晴氨、night 兩種顏色來(lái)實(shí)現(xiàn)切換。
相比自定義適配碉输、使用 Material Design Components 適配從設(shè)計(jì)的角度上更加規(guī)范籽前,同時(shí)對(duì) theme、attr敷钾、style 的不同使用場(chǎng)景也做了更加明確的區(qū)分聚假,通過(guò) theme 來(lái)規(guī)范屬性,在控件中不直接操作顏色闰非,而是通過(guò)屬性來(lái)操作顏色膘格,因?yàn)閷傩跃哂忻鞔_的場(chǎng)景意義。
而 colors 就只需要定義一份财松,這里推薦使用于顏色本身來(lái)命名瘪贱。
上面就是我針對(duì) light、night 分別定義的兩份 theme辆毡。
你有沒(méi)有發(fā)現(xiàn)這里我們不需要手動(dòng)定義 textColor 了菜秦,因?yàn)榍懊嬲f(shuō)了,Material Design Components 內(nèi)置了 12 種顏色舶掖,而我們的這個(gè) TextView 是位于 CardView 上面的球昨,CardView 的默認(rèn)顏色就是我們 theme 中定義的 colorSurface,TextView 的默認(rèn)顏色就是 colorOnSurface眨攘,所以我們只需要在 theme 中定義屬性來(lái)指明顏色就可以了主慰,這就是通過(guò)屬性來(lái)操作的好處,當(dāng)然前提是開(kāi)發(fā)人員必須熟悉 Material Design Components 的顏色規(guī)范鲫售。
切換主題
目前為止我們已經(jīng)知道了如何適配暗黑模式共螺,在完成適配之后,我們還需要為用戶提供在運(yùn)行時(shí)情竹,切換主題的選項(xiàng)藐不。
通常你可以在設(shè)置中為用戶提供切換的選項(xiàng),切換的代碼也很簡(jiǎn)單,通過(guò) delegate.localNightMode 來(lái)設(shè)置當(dāng)前的模式雏蛮。
有一點(diǎn)需要注意的是涎嚼,切換邏輯僅在運(yùn)行時(shí)生效,當(dāng)我們重新啟動(dòng) App 的時(shí)候挑秉,會(huì)與當(dāng)前系統(tǒng)設(shè)置的模式保持一致铸抑,所以當(dāng)用戶執(zhí)行完切換邏輯后,我們需要對(duì)用戶的行為進(jìn)行保存衷模,當(dāng)下一次重新啟動(dòng) App 的時(shí)候鹊汛,以恢復(fù)用戶之前的切換邏輯。
自定義切換邏輯
當(dāng)我們?cè)O(shè)置 delegate.localNightMode 的時(shí)候阱冶,系統(tǒng)會(huì)自動(dòng)重新創(chuàng)建 Activity刁憋,如果你不想要重新創(chuàng)建,可以在 manifest 中對(duì)應(yīng)的 Activity 中指定 android:configChanges="uiMode"木蹬,然后重寫(xiě) onConfigurationChanged() 方法至耻,自己來(lái)處理切換邏輯渤闷。
至此所有關(guān)于 Android App 的 Dark Mode 適配的內(nèi)容就介紹到這里俐东,關(guān)于更多 Dark Mode 的資料以及本文中 demo 的倉(cāng)庫(kù),關(guān)注本公眾號(hào)【Android|Kotlin】回復(fù)【暗黑】可以獲取全部?jī)?nèi)容主胧。
感謝你的觀看晦譬,如果對(duì)你有用疤苹,請(qǐng)點(diǎn)個(gè)好看,分享轉(zhuǎn)發(fā)這篇文章敛腌,這將會(huì)對(duì)我有很大的幫助卧土,謝謝!