#前言
很多優秀的APP都支持多種主題,最常見的是白天和夜間模式。因此本篇博客是作者實踐更換主題的記錄,寫出來與大家分享。
實現更換主圖這一功能有很多種方式,最簡單的方式,就是定義多套主題。至於style文件當中,也適合新手學習與實踐(大神勿噴)。言歸正傳,進入主題。
#定義需要在各種主題下切換的屬性
這部分內容放在values下的attrs.xml文件中,這裏我簡單定義了幾個如下:
<resources>
<attr name="rootViewBg" format="reference|color"/>
<attr name="titleBg" format="color"/>
<attr name="buttonBg" format="color"/>
<attr name="textColor" format="reference|color"/>
<attr name="buttonTextColor" format="color"/>
</resources>
#定義多種主題
既然是主題,自然是放在style.xml文件當中,這裏以我的style文件爲例,大家參考下,重點看註釋裏的日間模式和夜間模式:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="FullscreenTheme" parent="AppTheme">
<item name="android:actionBarStyle">@style/FullscreenActionBarStyle</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowBackground">@null</item>
<item name="metaButtonBarStyle">?android:attr/buttonBarStyle</item>
<item name="metaButtonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
</style>
<style name="FullscreenActionBarStyle" parent="Widget.AppCompat.ActionBar">
<item name="android:background">@color/black_overlay</item>
</style>
<!--日間模式-->
<style name="Theme_Day" parent="AppTheme">
<item name="rootViewBg">@color/white</item>
<item name="textColor">@color/black_overlay</item>
<item name="buttonBg">#383838</item>
<item name="buttonTextColor">#008888</item>
</style>
<!--夜間模式-->
<style name="Theme_Night" parent="AppTheme">
<item name="rootViewBg">@color/black_overlay</item>
<item name="textColor">@color/white</item>
<item name="buttonBg">#000090</item>
<item name="buttonTextColor">#008811</item>
</style>
</resources>
#將屬性應用到佈局文件當中
佈局文件比較簡單,就是將我們自己定義的一些屬性,應用到我們需要在不同主題下需要變更的View屬性,注意代碼當中註釋的地方,比較簡單,不做太多的講解。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/rootViewBg">
<!--注意這裏哦-->
<Button
android:id="@+id/bt"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="修改主題" />
<view.CircleProgress
android:id="@+id/circle_progress_welcome"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerInParent="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="40dp"
android:text="@string/wasu_phone_tv"
android:textSize="30sp"
android:textStyle="bold"
android:typeface="serif"
android:textColor="?attr/textColor"/>
<!--注意這裏哦-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:text="@string/verion_info"
android:textColor="@color/white" />
</RelativeLayout>
#AndroidManifest.xml文件中,應用默認的自定義主題
先看我的AndroidManifest.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wasu.winton.phonetv">
<application
android:name=".BaseApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name="activity.WelcomeActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:theme="@style/Theme_Night">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="activity.LoginActivity"
/>
<activity android:name="activity.IndexActivity"/>
</application>
</manifest>
注意一下我的第一個Activity中android:theme
的值爲我自定義的主題,爲什麼呢?因爲只有自定義主題中,才包含了我自定義的屬性呀,如果使用android:theme:@style/AppTheme
會報運行時異常的,因爲很多網上的例子,都沒說這一點,我這裏浪費了好幾個小時。
報出的異常:android.view.InflateException
android.view.InflateException: Binary XML file line #1: Error inflating class android.widget.RelativeLayout
#Activity中切換主題
主要就是這兩個方法,這兩個方法都是放在Activity的onCreate()方法中。通過將使用哪種主題寫入SharePerfence文件,保證重新創建Activity可以生效。
public void initView() {
if(PerferenceUtil.getSp().getBoolean("dark",false)){
//配置文件中讀取
setTheme(R.style.Theme_Day);
}else {
setTheme(R.style.Theme_Night);
}
setContentView(R.layout.activity_welcome);
circleProgress =(CircleProgress)findViewById(R.id.circle_progress_welcome);
circleProgress.startAnim();
bt = (Button)findViewById(R.id.bt);
}
@Override
public void initListener() {
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean theme = PerferenceUtil.getSp().getBoolean("dark", false);
PerferenceUtil.getEditor().putBoolean("dark",!theme).commit();//更換配置文件中主題
WelcomeActivity.this.recreate();//重新創建Activity
}
});
}
#效果
這種方式就是會出現閃現,怎麼改善,後序研究。