Android夜間模式(多主題)探索

若是本文幫助到你,本人不勝榮幸,若是浪費了你的時間,本人深感抱歉。 但願用最簡單的大白話來幫助那些像我同樣的人。若是有什麼錯誤,請必定指出,以避免誤導你們、也誤導我。 本文來自:www.jianshu.com/users/320f9… 感謝您的關注。android

主題功能老早就想研究了,但是看了不少以後,發現想要很好的實現,並無什麼簡單的辦法。 可是若是要求不高,實現起來仍是挺簡單的。 一塊兒來看一下。git


先說說簡單的實現步驟

  1. 在 styles.xml 中定義不一樣的主題風格;
  1. 在 attrs.xml 文件中,定義本身的屬性;
  2. 在 layout 佈局文件中,使用 styles.xml 中定義的屬性;
  3. 在 Activity 中切換主題,就行了。

而後來看每一步的詳細操做:github

1. 在 styles.xml 中定義不一樣的主題風格

也就是定義多種風格的主題,設置不一樣的顏色等。框架

<resources>
	<style name="AppTheme" parent="Theme.AppCompat.Light">
		<!--Toolbar的背景顏色-->
		<item name="colorPrimary">@color/colorPrimary</item>
		<!--StatusBar的顏色-->
		<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
		<!--主標題的字體顏色-->
		<item name="android:textColorPrimary">@color/textColorPrimary</item>
		<!--控制元件的默認狀態顏色-->
		<item name="android:colorControlNormal">@color/colorControlNormal</item>
		<!--控制元件在選中狀態的顏色-->
		<item name="colorAccent">@color/colorAccent</item>
		<!--Activity的背景顏色-->
		<item name="android:windowBackground">@color/windowBackground</item>
		<!--自定義的屬性-->
		<item name="Text_bg_Color">@color/Text_bg_Color</item>
	</style>

	<style name="AppThemeNight" parent="Theme.AppCompat.Light">
		<item name="colorPrimary">@color/NcolorPrimary</item>
		<item name="colorPrimaryDark">@color/NcolorPrimaryDark</item>
		<item name="android:textColorPrimary">@color/NtextColorPrimary</item>
		<item name="android:colorControlNormal">@color/NcolorControlNormal</item>
		<item name="colorAccent">@color/NcolorAccent</item>
		<item name="android:windowBackground">@color/NwindowBackground</item>
		<item name="Text_bg_Color">@color/NText_bg_Color</item>
	</style>
</resources>
複製代碼

大多時候,系統自帶的屬性並不夠用,因此就須要自定義一些屬性,好比說上面的最後一個屬性。 自定義方法以下less

2. 在 attrs.xml 文件中,定義本身的屬性

在values文件夾下,新建attrs.xml文件,定義本身的屬性。ide

<resources>
    <attr name="Text_bg_Color" format="color"/>
</resources>
複製代碼

3. 在 layout 佈局文件中,使用 styles.xml 中定義的屬性

佈局文件中,在須要改變色調的位置,設置相應的屬性。佈局

佈局文件

4. 最後一步,在 Activity 中切換主題

public class MainActivity extends AppCompatActivity {

	/**
	 * recreate() 會使 Activity 從新刷新,因此 這個標誌必須是靜態的。
	 */
	private static boolean night = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		changeTheme();
		setContentView(R.layout.activity_main);

		findViewById(R.id.email_sign_in_button).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View view) {
				change();
			}
		});
	}

	private void change() {
		night = !night;
		changeTheme();
		recreate();// 重啓 Activity
	}

	/**
	 * 根據標誌改變主題
	 */
	private void changeTheme() {
		if (night) {
			setTheme(R.style.AppThemeNight);
		} else {
			setTheme(R.style.AppTheme);
		}
	}
}
複製代碼

到此,就能夠實現一個最基本的切換主題了,這樣也是會有一個問題,也就是閃屏。 可是若是要求不是很高,這也是能夠知足需求的。 此項目代碼: github.com/Wing-Li/And…字體


閃屏也是你們想盡各類辦法想要解決的一個問題。spa

在此寫下你們解決的思路。3d

目前思路是:
  1. 利用 setTheme(); 改變主題;
  2. 用 recreate() 刷新當前Activity,主題就改變了。
解決閃屏辦法:

再也不使用 setTheme(); 而是將當前 Activity 上的每一個控件,分別改爲本身設定的顏色。

對,沒錯,就是修改每一個控件。 各類解決辦法,也就是看使用什麼辦法能夠更方便的修改多個控件。


找到了兩個切換主題的框架,從源碼中很明顯的能夠看出,他們都是把經常使用的基本控件重寫的一遍,而咱們要使用這個框架的時候,也必須使用框架所提供的控件。

當調用了切換主題的方法後,會遍歷使用的控件修改相應的顏色,從而達到 不閃屏切換主題的效果。

github.com/Bilibili/Ma…

MagicaSakura

github.com/dersoncheng…

MultipleTheme



若是是有多個主題,用框架實現還能接受,畢竟很麻煩。 可是若是僅僅只是要實現夜間模式,就使用個框架仍是不太舒服,並且必需要使用框架帶的基本控件。

因此仍是有一些其餘的方式,目的仍是那句話:使用更好的方式修改多個控件的顏色。 這篇文章介紹的方法,感受不錯:知乎和簡書的夜間模式實現套路 前面都大同小異,主要是修改顏色的那一段代碼。

將其項目提煉後,只剩修與修改主題相關代碼: github.com/Wing-Li/And…

好了,本文就分享到這裏。 若是有什麼更好的方式,請必定告知。
相關文章
相關標籤/搜索