日夜间模式我我们常用的一个功能,那具体要怎么做呢?
主要用两种比较好的方法
第一种简而言之:持久化theme再recreate再取出theme,在setContentView前使用setTheme方法
第二种使用 Support Library 23.2.0 DayNight主题实现
先说第一种
第一种的好处是不仅是日夜模式,还可以自定义很多自己的模式
首先写一下自己的持久化工具SPUtil
这个工具采用了单例模式,而且将SharedPreferences和SharedPreferences.Editor整合在一起,方便储存和读取
public class SPUtil {
private static SPUtil instance;
private SharedPreferences sp;
private SharedPreferences.Editor editor;
private SPUtil(Context context) {
sp = context.getSharedPreferences("sp", context.MODE_PRIVATE);
editor = sp.edit();
}
public static void init(Context context) {
instance = new SPUtil(context);
}
//最好加个线程锁,怕同时修改有冲突
public static synchronized SPUtil getInstance() {
if (instance != null) {
return instance;
} else {
return null;
}
}
public boolean putString(String key, String value) {
editor.putString(key, value);
return editor.commit();
}
public String getString(String key) {
return sp.getString(key, "");
}
public boolean putInt(String key, int value) {
editor.putInt(key, value);
return editor.commit();
}
public int getInt(String key, int defaultValue) {
return sp.getInt(key, defaultValue);
}
public boolean putLong(String key, long value) {
editor.putLong(key, value);
return editor.commit();
}
public long getLong(String key, long defaultValue) {
return sp.getLong(key, defaultValue);
}
public boolean putFloat(String key, float value) {
editor.putFloat(key, value);
return editor.commit();
}
public float getFloat(String key, float defaultValue) {
return sp.getFloat(key, defaultValue);
}
}
然后在新建一个Application类,在oncreate方法里初始化这个工具
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SPUtil.init(this);
}
}
到AndroidManifest.xml里修改Application的名字,改为自己的Application类名
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name=".MyApplication"
android:supportsRtl="true"
android:theme="@style/AppTheme">
然后再写一个自定义的Theme
<style name="NightTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#1f2023</item>
<item name="colorPrimaryDark">#18181a</item>
<item name="colorAccent">#FF4081</item>
<item name="android:background">#312F31</item>
然后再写逻辑代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//获取Theme的id
int style=SPUtil.getInstance().getInt("MyMode",R.style.AppTheme);
//调用setTheme
setTheme(style);
setContentView(R.layout.activity_main);
Button btn= (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//持久化Theme
SPUtil.getInstance().putInt("MyMode",R.style.NightTheme);
recreate();
}
});
}
}
还有关于recreate后Activity状态的保存问题,只要控件有id就可以保存
效果如图
效果图第二种方法
首先也要像第一种方法一样设一个持久化的工具
DayNight主题主要有四种
MODE_NIGHT_NO | 使用亮色(light)主题 |
---|---|
MODE_NIGHT_YES | 使用暗色(dark)主题 |
MODE_NIGHT_AUTO | 根据当前时间自动切换 亮色(light)/暗色(dark)主题 |
MODE_NIGHT_FOLLOW_SYSTEM | 设置为跟随系统 |
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn= (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//设置为夜间模式
getDelegate().setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_YES);
//持久化mode
SPUtil.getInstance().putInt("mode", AppCompatDelegate.MODE_NIGHT_YES);
recreate();
}
});
}
}
这种方法不用每个Activity都setTheme,使用setDefaultNightMode方法后全局都换主题,但如果想保存当前主题的状态要在oncreate区取出这个主题的id,再调用方法setDefaultNightMode
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SPUtil.init(this);
int mode=SPUtil.getInstance().getInt("mode", AppCompatDelegate.MODE_NIGHT_NO);
AppCompatDelegate.setDefaultNightMode(mode);
}
}
最后还要设置night主题特定的属性
在res下面创建values-night的values文件夹,去到Project层里找到相应文件夹
project层
新建一个colors文件,就可以自定义夜间模式时的属性
如
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#1f2023</color>
<color name="colorPrimaryDark">#18181a</color>
<color name="colorAccent">#FF4081</color>
</resources>
效果如下
效果图如果大家觉得recreate有点生硬的话还可以加点动画哦
网友评论