一羡棵、android 平臺常見的換膚方案.
Android 平臺常見的額換膚方式總結(jié)起來有如下三種:
1.設(shè)置setTheme 主題來切換金抡。
- 原理:通過在values文件夾下的attrs.xml和style.xml文件中配置不同的風(fēng)格的主題敢朱,在Activity中的onCreate()方法中位喂,調(diào)用setContentView()方法前調(diào)用setTheme()方法來設(shè)置主題疗垛。
- 優(yōu)點:利用系統(tǒng)自帶的機(jī)制實現(xiàn)挠阁,根據(jù)標(biāo)志位setTheme()即可宾肺。
- 缺點:在主題切換界面不重啟的情況下,不能自動完成界面主題的刷新侵俗。笨重锨用,靈活性較低,不易于擴(kuò)展隘谣。
- 例如:
android 設(shè)置自定義主題及切換方案
2.借助于第三方庫完成換膚
- 原理:LayoutInflater有一個內(nèi)部接口Factory黔酥,系統(tǒng)會使用它去做XML到View的轉(zhuǎn)換,而系統(tǒng)也提供了setFactory的方法洪橘,用戶設(shè)置了跪者,則用我們設(shè)置的,這樣系統(tǒng)就會走我們Factory的onCreateView,他會返回一個我們定制化的View熄求。
- 優(yōu)點:不用重啟activity渣玲,不閃屏;可以為程序提供多種皮膚方案不局限于夜間/白天模式弟晚。
- 缺點:在制作方面代價過大忘衍,侵入性較強(qiáng)逾苫,需要以來第三方庫完成,可靠性不能得到保證枚钓。
- 例如:
ChangeSkin
Android-skin-support
3:使用DayNight主題實現(xiàn)來支持日間/夜間模式的切換
- 優(yōu)點:Google自家產(chǎn)品铅搓,可靠性高,配置簡單搀捷,省心省力星掰,在僅僅需要實現(xiàn)夜間/日間模式的應(yīng)用內(nèi)強(qiáng)烈推薦。
- 缺點:不支持多皮膚切換嫩舟,只支持日間模式和夜間模式氢烘。
二.官方DayNight主題方案實現(xiàn)
1.導(dǎo)入依賴
implementation 'androidx.appcompat:appcompat:1.0.2'
2.修改style文件
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/color_blue</item>
</style>
在這里需要將主題改為Theme.AppCompat.DayNight 或者它的子主題。只有這樣才支持白夜模式的切換家厌。
這會將應(yīng)用程序的主題與系統(tǒng)控制的夜間模式標(biāo)志相關(guān)聯(lián)播玖,當(dāng)系統(tǒng)的主題切換時,應(yīng)用也會隨之切換主題饭于。
3.新增夜間模式下的color文件
既然App需要在白夜模式下互相切換蜀踏,就需要兩套的顏色資源文件和圖片資源文件。
顏色資源文件
原有的color.xml文件內(nèi)的顏色系統(tǒng)默認(rèn)作為白天模式下的顏色取值掰吕。對于夜間模式脓斩,我們需要新增values-night文件夾,里面包含一個新建的color文件
圖片資源文件
如果適配圖片的話畴栖,就創(chuàng)建對應(yīng)的 drawable-night-xxhdpi目錄,mipmap-night-xxhdpi目錄然后將圖片資源放到對應(yīng)的目錄里面八千。
在這個文件中的顏色名需與默認(rèn)的color文件內(nèi)顏色名一一對應(yīng)
//默認(rèn)的color文件內(nèi)顏色值
<color name="color_1">#f2f2f2</color>
<color name="color_2">#8E8E93</color>
<color name="color_3">#3385FF</color>
//values-night 內(nèi)的color文件內(nèi)顏色值
<color name="color_1">#616161</color>
<color name="color_2">#E0E0E0</color>
<color name="color_3">#E0E0E0</color>
4.切換模式
開始前我們要確保我們的Activity繼承自AppCompatActivity.
兩種方法:
第一種:調(diào)用AppCompatActivity里的getDelegate()獲取AppCompatDelegate對象吗讶,然后在調(diào)用setLocalNightMode()方法設(shè)置夜間模式
if(isNi) {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
第二種:在onCreate()方法里的setContentView()方法前,直接調(diào)用AppCompatActivity里的靜態(tài)方法setDefaultNightMode()來設(shè)置
//日間 切換 夜間
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
recreate()
//夜間 切換 日間
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
recreate()
兩種方法的區(qū)別
第一種方法是立刻生效的恋捆,且只在當(dāng)前Activity有效照皆,代碼執(zhí)行之后會重新創(chuàng)建當(dāng)前Activity;而第二種方法是在Activity被創(chuàng)建的時候生效沸停,且對App內(nèi)的所有Activity都生效膜毁。
使用上述兩種方案就完成了切換。當(dāng)然這樣切換是很生硬的愤钾,沒有過渡動畫瘟滨,看起來不是很舒服 我們可以在recreate()之前給它加個過渡動畫.
getWindow().setWindowAnimations(R.style.OutInAnimation);
AppCompatDelegate一共有四種模式:
- MODE_NIGHT_NO. Always use the day (light) theme(一直應(yīng)用日間(light)主題).
- MODE_NIGHT_YES. Always use the night (dark) theme(一直使用夜間(dark)主題).
- MODE_NIGHT_AUTO. Changes between day/night based on the time of day(根據(jù)當(dāng)前時間在day/night主題間切換).自動模式,當(dāng)我們的APP有網(wǎng)絡(luò)及定位權(quán)限時能颁。系統(tǒng)會根據(jù)當(dāng)?shù)氐臅r間判斷當(dāng)前時處于白天還是黑夜杂瘸,從而自動加載不同的模式。
- MODE_NIGHT_FOLLOW_SYSTEM(默認(rèn)選項). This setting follows the system’s setting, which is essentially MODE_NIGHT_NO(跟隨系統(tǒng)伙菊,通常為MODE_NIGHT_NO).
當(dāng)我們的App啟動時就需要顯示為夜間模式時败玉,我們可以在Application內(nèi)設(shè)置
class BaseApplication : Application() {
static {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
override fun onCreate() {
super.onCreate()
}
但一般情況下敌土,我們都會在切換模式時將當(dāng)前模式保存至本地,下次啟動時再根據(jù)保存的值加載不同的模式
class BaseApplication : Application() {
override fun onCreate() {
super.onCreate()
if (SPManager.getBoolean(applicationContext, SPContent.SP_MODE, false))
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) else
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
}
5.注意
1.切換只作用于新生成的組件运翼,對原先處于任務(wù)棧中的Activity不起作用返干。(解決方法:發(fā)送廣播,讓它重啟)如果直接在Activity的onCreate()中調(diào)用切換代碼血淌,可以不需要調(diào)用recreate()矩欠。對于一些數(shù)據(jù)的保存與切換后的顯示我們可以用savedInstanceState來保存與復(fù)原
2.在切換后可以不調(diào)用recreate(),而是自己添加一個重啟該Activity的方法六剥,然后加個過度動畫
3.解決動態(tài)切換主題時activity重啟閃屏的問題:NightModel
感謝:
Android 10適配要點晚顷,深色主題-郭霖
android夜間模式淺析
一種Android換膚機(jī)制的實現(xiàn)