欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

主题切换ThemeChangeDemo(白天和夜间切换)

程序员文章站 2022-05-15 10:02:23
...

白天和黑夜主题切换

实现效果

主题切换ThemeChangeDemo(白天和夜间切换)

  1. 首先就是需要在app中准备两套主题:

    白天主题

    在values文件夹中创建styles.xml

    <resources>
    
       <style name="DayTheme" parent="Theme.AppCompat.Light.DarkActionBar">
           <!-- Customize your theme here. -->
           <item name="colorPrimary">#03A9F4</item>
           <item name="android:textColorPrimary">#ffffff</item>
           <item name="android:windowBackground">@color/background_material_light</item>
           <item name="colorAccent">#00BCD4</item>
           <item name="colorControlNormal">#00BCD4</item>
    
           <item name="titleStyle">@style/DayTitleStyle</item>
           <item name="contentStyle">@style/DayContentStyle</item>
           <item name="buttonBg">#2196F3</item>
           <item name="buttonTextColor">#ffffff</item>
           <item name="checkTextColor">#2196F3</item>
           <item name="switchTextColor">#2196F3</item>
       </style>
    
       <style name="DayTitleStyle">
           <item name="android:textColor">#212121</item>
           <item name="android:textSize">20sp</item>
           <item name="android:layout_margin">8dp</item>
       </style>
    
       <style name="DayContentStyle">
           <item name="android:textColor">#9C27B0</item>
           <item name="android:textSize">16sp</item>
           <item name="android:layout_margin">16dp</item>
           <item name="android:maxLines">10</item>
       </style>
    
    </resources>

    夜间主题

    在values文件夹中创建styles2.xml

    <resources>
    
       <style name="NightTheme" parent="Theme.AppCompat.Light.DarkActionBar">
           <!-- Customize your theme here. -->
           <item name="colorPrimary">#00796B</item>
           <item name="android:textColorPrimary">#212121</item>
           <item name="android:windowBackground">@color/background_material_dark</item>
           <item name="colorAccent">#00796B</item>
           <item name="colorControlNormal">#212121</item>
    
           <item name="titleStyle">@style/NightTitleStyle</item>
           <item name="contentStyle">@style/NightContentStyle</item>
           <item name="buttonBg">#00796B</item>
           <item name="buttonTextColor">#9E9E9E</item>
           <item name="checkTextColor">#212121</item>
           <item name="switchTextColor">#212121</item>
       </style>
    
       <style name="NightTitleStyle">
           <item name="android:textColor">#212121</item>
           <item name="android:textSize">20sp</item>
           <item name="android:layout_margin">8dp</item>
       </style>
    
       <style name="NightContentStyle">
           <item name="android:textColor">#212121</item>
           <item name="android:textSize">16sp</item>
           <item name="android:layout_margin">16dp</item>
           <item name="android:maxLines">10</item>
       </style>
    
    </resources>

  2. 创建自定义属性

    上面这两套主题中,各个属性定义完全一模一样,不一样的只是属性的值,其中在DayTheme和NightTheme的style中有这么一段代码:

    <item name="titleStyle">@style/DayTitleStyle</item>
    <item name="contentStyle">@style/DayContentStyle</item>
    <item name="buttonBg">#2196F3</item>
    <item name="buttonTextColor">#ffffff</item>
    <item name="checkTextColor">#2196F3</item>
    <item name="switchTextColor">#2196F3</item>

    正常情况下style中是不存在这些属性的,它们这些是自定义属性,主要是用来控制某些控件或者布局的属性,它们的定义在attrs文件中:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
       <attr name="contentStyle" format="reference"/>
       <attr name="titleStyle" format="reference"/>
       <attr name="buttonBg" format="reference|color"/>
       <attr name="buttonTextColor" format="reference|color"/>
       <attr name="checkTextColor" format="reference|color"/>
       <attr name="switchTextColor" format="reference|color"/>
    </resources>

  3. 在布局文件 layout_main 中引用相应属性

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:tools="http://schemas.android.com/tools"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical"
       tools:context=".MainActivity">
    
       <TextView
           style="?attr/titleStyle"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@string/title" />
    
       <TextView
           style="?attr/contentStyle"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@string/hello_world" />
    
       <CheckBox
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="CheckBox"
           android:textColor="?attr/checkTextColor" />
    
       <CheckBox
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="CheckBox"
           android:textColor="?attr/checkTextColor" />
    
       <Switch
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Switch"
           android:textColor="?attr/switchTextColor" />
    
       <Button
           android:id="@+id/btn_setting"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="设置"
           android:background="?attr/buttonBg"
           android:textColor="?attr/buttonTextColor" />
    
    </LinearLayout>

  4. 切换主题

    ​ 有了两套主题了,接下来是通过代码来进行控制主题间的切换了,控制主题的切换其实就是通过setTheme(R.style.*)来设置不同的style从而达到界面风格的变换,不过这个方法setTheme()只在setContentView()方法前设置才有效,所以如果你想在其它地方调用这个方法来切换主题那是肯定不行的,所以这里有两个难点?

    1、怎么处理当前的设置界面在切换主题后同时切换主题风格

    2、怎么处理之前已经打开的界面让他们切换主题风格

    这里我给出的答案是:

    1、在当前切换主题的设置界面使用Activity.recreate()方法,该方法的作用就是当当前Activity的配置发生变化时,调用这个方法可以把当前Activity实例销毁并重新创建出一个Activity实例。如此可见通过这个方法可以很容易的解决问题一,因为它会重新创建一个新的Activity实例。

    2、这里我使用的方法是通过设置Intent的Flag来达到更新之前Activity的效果,通过设置mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);让它清除之前的Activity再创建一个新的Activity,这样当返回之前的界面就可以更新主题了。【注】如果有多个界面可以通过设置主界面MainActivity的launchMode为singleTask,在返回主界面时候清除其它界面来更新主题

    清单文件中

    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/DayTheme">
            <activity android:name=".MainActivity"
                android:label="@string/app_name"
                android:launchMode="singleTask">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name=".ChangeTheme"/>
        </application>

  5. 代码实现

    通过一个主题设置工具类设置主题,在每个Activity的setContentView()方法之前设置主题:

    设置主题工具类

    ThemeChangeUtil:

    public class ThemeChangeUtil {
       public static boolean isChange = false;
       public static void changeTheme(Activity activity){
           if(isChange){
               activity.setTheme(R.style.NightTheme);
           }
       }
    }

    设置选项界面

    acitvity_change.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:orientation="vertical" android:layout_width="match_parent"
       android:layout_height="match_parent">
    
       <Button
           android:id="@+id/btn_change"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:background="?attr/buttonBg"
           android:textColor="?attr/buttonTextColor"
           android:text="夜间/白天模式" />
    </LinearLayout>

    设置选项代码实现

    ThemeChange.java

    public class ChangeTheme extends AppCompatActivity {
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           ThemeChangeUtil.changeTheme(this);
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_change);
    
           Button mChangeBtn = (Button) findViewById(R.id.btn_change);
           mChangeBtn.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   if (ThemeChangeUtil.isChange) {
                       ThemeChangeUtil.isChange = false;
                   } else {
                       ThemeChangeUtil.isChange = true;
                   }
                   ChangeTheme.this.recreate();//重新创建当前Activity实例
               }
           });
       }
    
       @Override
       public void onBackPressed() {
           super.onBackPressed();
           Intent mIntent = new Intent(this, MainActivity.class);
           mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
           startActivity(mIntent);
           finish();
       }
    }

    主界面代码实现

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           ThemeChangeUtil.changeTheme(this);
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
    
           Button mSettingBtn = (Button) findViewById(R.id.btn_setting);
           mSettingBtn.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   MainActivity.this.startActivity(new Intent(MainActivity.this, ChangeTheme.class));
               }
           });
       }
    }

    完成切换主题

    参考博客:http://www.mamicode.com/info-detail-1013910.html

相关标签: 夜间主题