Android主題切換(一),基本使用流程
效果
前言
最近做的一個音樂類開源專案,有不少使用者反映,說介面主題膚色太單一,希望能夠提供多種顏色的主題供使用者選擇,剛好這段時間事情不多,就琢磨著為專案新增一個切換主題的功能。
在網上查閱了大量的資料、參考了各個App的主題切換效果,隨後做出了這個功能,專案介面立馬提高了一個檔次,期間遇到了不少的坑,效率不一定很高,但還是有參考價值的,特此記錄一下完成的過程。
我打算完成的主題切換包括白天模式(包括各種顏色的主題)、夜間模式。這裡白天模式的各主題之間是比較相似的,主要換了對應的幾種屬性顏色值,而他們和夜間模式之間的差別就稍微大一些,改變的不僅僅是公共的幾個顏色值,還有所有的背景色。
開始
Android Support Library 23.2提供了一個主題Theme.AppCompat.DayNight.它的出現使我們實現夜間模式變得更加容易,當然使用它之前需要先新增一下相應的依賴庫
compile 'com.android.support:appcompat-v7:24.2.1'
切換主題之前,我們需要先在res–>styles.xml中新增主題。
<style name="BiLiPinkTheme" parent="AppTheme">
<item name="colorPrimary">@color/biliPink</item >
<item name="colorPrimaryDark">@color/biliPink</item>
<item name="colorAccent">@color/biliPink</item>
<item name="image_tint">@color/biliPink</item>
<item name="press_color">@color/biliPink50</item>
</style>
<style name ="KuAnGreenTheme" parent="AppTheme">
<item name="colorPrimary">@color/kuanGreen</item>
<item name="colorPrimaryDark">@color/kuanGreen</item>
<item name="colorAccent">@color/kuanGreen</item>
<item name="image_tint">@color/kuanGreen</item>
<item name="press_color">@color/kuanGreen50</item>
</style>
<style name="NightModeTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="colorPrimary">@color/nightActionbar</item>
<item name="colorPrimaryDark">@color/nightActionbar</item>
<item name="colorAccent">@color/biliPink</item>
<item name="image_tint">@android:color/white</item>
<item name="appbg">@color/nightBg</item>
<item name="divider">@color/nightActionbar</item>
<item name="press_color">@color/biliPink50</item>
<item name="play_bar_color">@color/nightActionbar</item>
<item name="android:textColor">@color/colorWhite</item>
<item name="text_color">@color/colorWhite</item>
<item name="android:windowBackground">@color/nightBg</item>
<item name="android:listDivider">@drawable/divider_bg</item>
<item name="android:windowSoftInputMode">adjustPan|stateHidden</item>
<item name="android:windowAnimationStyle">@style/Animation</item>
<item name="alertDialogTheme">@style/Theme.AppCompat.Light.Dialog.Alert.Self</item>
</style>
其他非夜間模式繼承一個共同的父主題,夜間模式直接繼承Theme.AppCompat.DayNight類主題。
對於夜間模式,我們可以為其專門建立一個資原始檔夾,在res下建立一個values-night資料夾,裡面放著夜間主題樣式的color等資源。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--夜間模式下 通用背景色-->
<color name="common_bg">#2c2c2c</color>
<!--夜間模式下 觸控背景色-->
<color name="common_touch_bg">#3b3b3b</color>
</resources>
當然夜間模式各種屬性的名字和白天模式下的名字必須一樣,值可以任意設定我們想要的值。這樣我們就為白天模式和夜間模式分配了不同的資原始檔。
切換主題
接下來我們應該要做一個主題選擇的Activity,在這個Activity中響應使用者的操作切換不同的主題,Activity這塊大家都會就不說了,說一下主題切換的核心程式碼(這裡僅僅只是介紹白天模式、夜間模式的設定,其他主題後續篇章會再做講解)。
public static void setNightMode(Context context, boolean isNight) {
if (isNight) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
SharedPreferences sharedPreferences = context.getSharedPreferences(Constant.THEME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("night", isNight).commit();
}
這裡使用SharedPreferences 儲存夜間模式,不容易丟失,同時AppCompatDelegate.setDefaultNightMode(int mode);
這裡的mode有四個可選值,分別是:
- MODE_NIGHT_NO:強制不使用夜間主題
- MODE_NIGHT_YES:強制使用夜間主題
- MODE_NIGHT_AUTO:根據當前時間自動切換 夜間/非夜間主題
- MODE_NIGHT_FOLLOW_SYSTEM:預設設定,跟隨系統主題
設定主題
Android在Activity中給我們提供了一個方法叫setTheme(int id),看名字就知道是專門用來設定主題的,但是有個地方需要注意,這個方法必須在setContentView(int id) 之前呼叫,也就是在Activity建立之初才能設定主題。
setTheme(R.style.NightModeTheme);
結束
Android設定主題的大致流程這裡做了簡單的介紹,至此也能夠實現簡單的demo,達到切換主題的效果,但是你如果只照上面的方法應用到專案中你會發現還有很多問題,比如:既然必須在Activity中setContentView(int id) 之前呼叫setTheme(int id)方法,那怎麼辦呢?重啟當前Activity?重啟發現會閃屏怎麼解決?設定完主題返回發現還是原來的主題,是不是沒設定成功?設定background屬性使用selector的時候內建?attr以達到不同主題使用不同資源報錯?等等等等,還有許多問題需要解決,這些也是我在實現主題切換的時候遇到的問題,在後續的篇章中我會寫出我的解決方案供大家參考。
專案
可能我的文字表達的並不是很清楚,大家也可以看我專案中的程式碼是怎麼實現的,大家如果覺得不錯的話給個start唄。
App已經上架到酷安應用市場,大家也可以到酷安網搜“聽聽音樂”下載