當(dāng)下各種閱讀類APP(如各種瀏覽器,某日頭條等)都會有夜間模式,也順應(yīng)了大家的睡前必須玩一下手機的作息習(xí)慣。關(guān)于夜間模式的實現(xiàn),有很多種方法。這篇日志學(xué)習(xí)一下最簡單的實現(xiàn)方式,通過setTheme(int resid)方法實現(xiàn)主題切換來實現(xiàn)夜間模式,這也是Android官方推薦的方法。
整體思路與效果##
通過Android SDK提供的setTheme方法,可以切換Activity的不同的主題,這樣定義一個合適的主題,就可以實現(xiàn)夜間模式了。
首先看一下效果圖
定義不同的主題##
自定義主題屬性###
<resources>
<attr name="textColorValue" format="color" />
...
</resources>
這里我們可以定義一些切換時,需要更改的內(nèi)容屬性。比如說,當(dāng)前頁面中所有文字的顏色,在平時是黑色,在夜間模式是灰色,那么可以在這里定義一個屬性,在自定義主題時設(shè)置不同的顏色即可。
自定義不同的主題###
<!--日間模式主題-->
<style name="CustomThemeLight" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/light</item>
<item name="colorPrimaryDark">@color/light</item>
<item name="colorAccent">@color/black</item>
<item name="android:textColorPrimary">@color/black</item>
<item name="android:windowBackground">@color/white</item>
<item name="textContent">@string/theme0</item>
<item name="textColorValue">@color/black</item>
<item name="pupwindowTheme">@style/AppTheme.PopupLight</item>
</style>
<!--夜間模式主題-->
<style name="CustomThemeDark" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/dark_bg</item>
<item name="colorPrimaryDark">@color/dark_bg</item>
<item name="colorAccent">@color/dark_bg</item>
<item name="android:windowBackground">@color/dark_bg</item>
<item name="textContent">@string/theme1</item>
<item name="textColorValue">@color/white</item>
<item name="pupwindowTheme">@style/AppTheme.PopupDark</item>
</style>
熟悉ToolBar的同學(xué),應(yīng)該對上面幾個屬性不陌生。這里首先設(shè)置了colorPrimary,colorPrimaryDark,windowBackground等幾個屬性,首先確定了這個主題整體的色調(diào)。
接下來就是對自定義屬性的設(shè)置,這里我們可以看到在textColorValue的屬性在日間模式和夜間模式中分別設(shè)置成了黑色和白色,這樣就可以和整體的色調(diào)形成反差。
自定義屬性的使用###
接下來,就是將自定義屬性作用到布局文件中
<RelativeLayout
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:padding="10dp"
android:text="公開文章"
android:textColor="?attr/textColorValue"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:drawablePadding="10dp"
android:drawableRight="@mipmap/right_arrow"
android:gravity="center_vertical"
android:padding="10dp"
android:text="11"
android:textColor="?attr/textColorValue" />
</RelativeLayout>
如上面這段代碼所示,你可以將應(yīng)用中所有TextView的TextColor的屬性設(shè)置為?attr/textColorValue,這樣他的值就會根據(jù)你在自定義主題中所設(shè)定的值變化。這樣是不是比通過java代碼寫一大串if-else方便許多呢。
到這里你應(yīng)該想到了,在自定義屬性時可以定義各種各樣的內(nèi)容,TextView的大小,ImageView的大小,LinearLayout的背景等等。雖然這樣在一開始寫代碼的時候有些繁瑣,但從長遠來說,是很有價值的。
主題切換##
這里首先需要明確一點,setTheme方法必須在setContentView方法之前執(zhí)行,才會有效(這個有點讓人失望,但想想也是必然的),所以呢,采用這種方式實現(xiàn)夜間模式,Activity必然需要重啟,因此這里需要考慮到Activity切換的問題,不能讓人覺得換了一個夜間模式,整個應(yīng)用重啟了一遍,那也太low了。
Activity切換效果###
activity.finish();
activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
這里只需定義兩個動畫效果,確保Activity切換效果不明顯即可,采用alpha動畫即可,這個實現(xiàn)起來應(yīng)該很簡單,這里就不再贅述。
主題切換實現(xiàn)###
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
Util.onActivityCreateSetTheme(this);
setContentView(R.layout.activity_main);
}
這里我們在setContentView方法之前調(diào)用setTheme方法
主題切換工具類util###
public static void onActivityCreateSetTheme(Activity activity) {
switch (sTheme) {
case Constants.THEME_DARK:
activity.setTheme(R.style.CustomThemeDark);
break;
case Constants.THEME_LIGHT:
activity.setTheme(R.style.CustomThemeLight);
break;
default:
break;
}
}
這樣就為當(dāng)前Activity設(shè)置了相應(yīng)的主題。
調(diào)用下面的方法,傳入不同的主題id即可實現(xiàn)主題切換
public static void changeToTheme(Activity activity, int theme) {
sTheme = theme;
activity.finish();
activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
activity.startActivity(new Intent(activity, activity.getClass()));
}
好了,這里就是關(guān)于夜間模式的簡單了解。這種方式,相對來說比較繁瑣,但也最容易理解。當(dāng)然,這里只是從最簡單的角度出發(fā),沒有考慮Activity重啟前后數(shù)據(jù)保存和恢復(fù)的問題,以及對Fragment的影響等問題,實際問題還是需要根據(jù)實際項目分析,這里就不展開來說。
完整代碼已上傳到github,有興趣的同學(xué)可以參考一下。
這里對于自定義屬性和主題的用法,還是值得借鑒,即便不一定要用到夜間模式,但是通過切換主題實現(xiàn)UI的更新也是一種考慮。
PS:最近工作較忙,只能在睡前打開簡書看看文章,真心覺得簡書的夜間模式太棒了,一鍵切換,沒有過場動畫(不像某些瀏覽器),太高大上了。