1. 程式人生 > >Android夜間模式實現

Android夜間模式實現

開源實驗室 開源實驗室 » Android技術講解 » 正文

Android夜間模式實現


2015-05-26 By 張濤 | 累計訪問13200次

寫在前面

本文開源實驗室原創,轉載請以連結形式註明地址:
https://kymjs.com/code/2015/05/26/01

最近在做一個Android夜間模式的功能,又重新研究了一下Theme機制。貫徹我的風格,以解決問題為目標,寫了個小Demo,簡單了實現了切換夜間模式,為大家講解。

最近在做一個Android夜間模式的功能,又重新研究了一下Theme機制。貫徹我的風格,以解決問題為目標,寫了個小Demo,簡單了實現了切換夜間模式,為大家講解。
在Activity中有一個方法叫setTheme(),可以設定Activity的Theme,當然Application類中也有相同的方法,也可以在Application中設定當前應用的Theme。就好像我們可以在Manifest檔案中通過android:theme=“”來設定主題一樣。

建立屬性名

在工程目錄res/values/下新建一個xml檔案,名字可以自定義,這裡我的叫theme_attr.xml 內容如下:

 
	<?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等資料型別。

定義資源樣式

建立完屬性名後就需要建立主題樣式了。依舊在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必須直接或間接繼承系統的Theme,否則很多系統主題找不到就會報錯。
還有一點,我們聲明瞭兩個屬性,這裡一定要記得都把值定義了,如果不定義也不會錯。但是如果在程式碼中引用了相應的屬性,而這個主題沒有定義這個屬性的值會執行出錯的。
這裡可以看到因為上面我屬性型別定義了引用或顏色,所以這裡的值我既可以傳@drawable型別的引用也可以直接賦值一個#ff00ff這樣的顏色值。

佈局中使用

佈局檔案中使用我們自定義的檔案時,需要新增一個問號來表示引用。例如

 
	<LinearLayout xmlns:android="http://schemas.android.com/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呼叫之前呼叫setTheme()方法。網上有很多介紹都說的是在super之前,其實這種說法並不準確。當我們動態切換主題時,例如點選某個按鈕,切換主題,這個時候需要再次手動呼叫setContentView()方法,並重新呼叫控制元件初始化以及監聽器設定。但是這裡告訴你一種簡單方法:直接手動呼叫recreate()方法,再次建立檢視就可以了。

 
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;
        }
    }
}