最近在做一個Android夜間模式的功能,,又重新研究了一下Theme機制,。貫徹我的風格,以解決問題為目標,,寫了個小Demo,,簡單了實現(xiàn)了切換夜間模式,為大家講解,。
最近在做一個Android夜間模式的功能,,又重新研究了一下Theme機制。貫徹我的風格,,以解決問題為目標,,寫了個小Demo,簡單了實現(xiàn)了切換夜間模式,,為大家講解,。
在Activity中有一個方法叫setTheme(),可以設置Activity的Theme,,當然Application類中也有相同的方法,,也可以在Application中設置當前應用的Theme。就好像我們可以在Manifest文件中通過android:theme=“”來設置主題一樣,。
創(chuàng)建屬性名
在工程目錄res/values/下新建一個xml文件,,名字可以自定義,,這里我的叫theme_attr.xml 內(nèi)容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="text_bg" format="reference|color"/>
<attr name="bottom_bg" format="reference|color"/>
</resources>
其中text_bg和bottom_bg就是我們定義的兩個屬性名,后面的format是指的這個屬性名的類型,,這里我是用reference | color表示既可以是一個引用,,也可以是一個argb顏色值。除了這些你還可以選擇int,,boolan,string等數(shù)據(jù)類型,。 |
定義資源樣式
創(chuàng)建完屬性名后就需要創(chuàng)建主題樣式了,。依舊在res/values/下新建一個xml文件,或者也可以在原style.xml中寫,,是一樣的,。這里為了項目結構清晰,就單獨寫一個文件叫theme_dark.xml 我們需要在這里定義步驟一中定義的各屬性名在當前主題下的值,。
<resources>
<!-- Base application theme. -->
<style name="DarkTheme" parent="@android:style/Theme">
<item name="text_bg">@drawable/selector_text_bg_dark</item>
<item name="bottom_bg">@drawable/bg_bottombar_dark</item>
</style>
</resources>
需要注意的是,,我們自己定義的style必須直接或間接繼承系統(tǒng)的Theme,否則很多系統(tǒng)主題找不到就會報錯,。
還有一點,,我們聲明了兩個屬性,這里一定要記得都把值定義了,,如果不定義也不會錯,。但是如果在代碼中引用了相應的屬性,而這個主題沒有定義這個屬性的值會運行出錯的,。
這里可以看到因為上面我屬性類型定義了引用或顏色,,所以這里的值我既可以傳@drawable類型的引用也可以直接賦值一個#ff00ff這樣的顏色值。
布局中使用
布局文件中使用我們自定義的文件時,,需要添加一個問號來表示引用,。例如
<LinearLayout xmlns:android="http://schemas./apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/login_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?text_bg"
android:text="登錄"/>
</LinearLayout>
這樣就表示我們的登錄按鈕的背景使用的是前面定義的屬性名text_bg在當前主題下的值,也就是我們步驟二中定義的@drawable/selector_text_bg_dark這張圖片(其實是一個選擇器了)
代碼中使用
以一個最簡單的例子來說明了,,需要注意的是一定要在Activity的setContentView調(diào)用之前調(diào)用setTheme()方法,。網(wǎng)上有很多介紹都說的是在super之前,其實這種說法并不準確,。當我們動態(tài)切換主題時,,例如點擊某個按鈕,切換主題,,這個時候需要再次手動調(diào)用setContentView()方法,,并重新調(diào)用控件初始化以及監(jiān)聽器設置。但是這里告訴你一種簡單方法:直接手動調(diào)用recreate()方法,,再次創(chuàng)建視圖就可以了,。
public class UserInfor extends KJActivity {
@BindView(id = R.id.logout_btn, click = true)
private Button mBtnLogout;
@Override
public void setRootView() {
setContentView(R.layout.activity_userinfor);
}
@Override
public void widgetClick(View v) {
super.widgetClick(v);
switch (v.getId()) {
case R.id.logout_btn:
setTheme(R.style.DarkTheme);
recreate();
break;
}
}
}