Android使用系统自动SDK V7库实现切换主题
概述:google在v7:23.2.0之后引进了新方法那就是日夜间模式的主题切换,据说有很多坑,反正项目也没有具体用到这里写了个简单的demo加上了一个前辈填的坑,经验有限仅供参考^-^
1.添加依赖库
compile 'com.android.support:appcompat-v7:23.4.0'
只要是是在23.2.0以后的版本就可以
2.接着再上一张动图
3.分析
1首先创建一个ScrollingActivity,如果你要问为什么,自己去琢磨^-^haha:activity_scrolling.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="tangren.szxb.com.theme.ScrollingActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/icon_icon"
android:fitsSystemWindows="true" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_view" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email"
app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|end" />
</android.support.design.widget.CoordinatorLayout>
content_view.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="tangren.szxb.com.theme.ScrollingActivity"
tools:showIn="@layout/activity_scrolling">
</android.support.v7.widget.RecyclerView>
这样我们就把整体布局给写好了,其实这基本上都是自己生成的,这就是为什么要新建ScrollingActivity了
2其实切换主题这里就是切换style了,所以咱们要准备两套style、color等等
1 values\styles.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="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>
values\colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="colorText">#000000</color>
</resources>
2 新建values-night文件夹在res下,然后在values-night下新建style、color等配置xml,我这里style风格不变只是color有所改变
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#383838</color>
<color name="colorPrimaryDark">#333333</color>
<color name="colorAccent">#FF4081</color>
<color name="colorText">#A604bA</color>
</resources>
接下来就是代码部分了,首先官方给给咱们提供了四种状态:
public static final int MODE_NIGHT_NO = 1;
public static final int MODE_NIGHT_YES = 2;
public static final int MODE_NIGHT_AUTO = 0;
public static final int MODE_NIGHT_FOLLOW_SYSTEM = -1;
分别是不使用夜间模式,使用夜间模式,根据地理位置推算白天夜晚自动进入夜间或白天模式,根据Android系统设置的模式
当然你可以设置一个默认模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
或者自己切换
白天模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); activity.getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
夜间
模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); activity.getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
如果你有横竖屏的需求可能就会出现一点bug那就是横竖屏切换后可能会出现夜间模式跟白天模式混乱的情况,现有的解决办法是更新UI模式,但是你一定要找准时机不能随处更新,有人说google已经在23.4已经修复了此bug,暂未知……
public static void refershResource(AppCompatActivity activity) {
isNight = SpUtils.getBoolean(THEME_KEY, false);
if (isNight)
updateConfig(activity, Configuration.UI_MODE_NIGHT_YES);
else
updateConfig(activity, Configuration.UI_MODE_NIGHT_NO);
}
private static void updateConfig(AppCompatActivity activity, int uiNightModel) {
Configuration configuration = new Configuration(activity.getResources().getConfiguration());
configuration.uiMode &= ~Configuration.UI_MODE_NIGHT_MASK;
configuration.uiMode |= uiNightModel;
activity.getResources().updateConfiguration(configuration, null);
}
这里我贴一下application的代码吧,其实这里做一下初始化的东西,重点也都是这里的东西,下面我会留源码地址的
package tangren.szxb.com.theme;
import android.app.Application;
import android.content.res.Configuration;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
/**
* Created by Administrator on 2016/10/19 0019.
*/
public class MyApplication extends Application {
private static MyApplication application;
private static boolean isNight;
private static String THEME_KEY = "mode";
public static MyApplication getIntence() {
if (application == null) {
application = new MyApplication();
}
return application;
}
@Override
public void onCreate() {
super.onCreate();
this.application=this;
init();
}
private void init() {
isNight = SpUtils.getBoolean(THEME_KEY, false);
if (isNight)//夜间模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
else//默认为白天模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
public static void setThemeModel(AppCompatActivity activity, boolean model) {
if (isNight == model)
return;
if (!model)//白天模式
{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
activity.getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
activity.getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
isNight = model;
SpUtils.putBoolean(THEME_KEY, isNight);
activity.recreate();
}
public static void refershResource(AppCompatActivity activity) {
isNight = SpUtils.getBoolean(THEME_KEY, false);
if (isNight)
updateConfig(activity, Configuration.UI_MODE_NIGHT_YES);
else
updateConfig(activity, Configuration.UI_MODE_NIGHT_NO);
}
private static void updateConfig(AppCompatActivity activity, int uiNightModel) {
Configuration configuration = new Configuration(activity.getResources().getConfiguration());
configuration.uiMode &= ~Configuration.UI_MODE_NIGHT_MASK;
configuration.uiMode |= uiNightModel;
activity.getResources().updateConfiguration(configuration, null);
}
}