参考链接:
最近公司想做夜间模式,于是在网上进行了搜索,发现一些三方库已经很久不更新了,于是转而参考上面的两个链接,利用系统特性研究出一套夜间模式的方法,这套方法代码量比较小,适用性强,能够很好的满足我司当前的需求;
开发思路:我最开始看到的是链接1,然后根据链接1开搞的过程中发现,里面的示例代码不全,在xml中设置的字体颜色无法修改,本人能力有限,百度之后也无法解决这个问题,于是转而看网上的其他方法并找到了链接2,通过实践发现链接2可以很好的修改xml中设置的背景色和字体色以及自定义drawable背景中的颜色,完美弥补了链接1的不足,但是链接2不能对代码中动态设置的字体颜色和背景色进行修改,而链接1又很好的完成了这一点;于是二者结合,成功解决夜间模式问题
总结:
链接1:负责修改代码中动态设置的字体颜色和背景色;
链接2:负责修改 xml 和 drawable 中设置的字体颜色和背景色;
链接1的实现思路:
1:创建res-night文件夹,注意一定要和 res 文件夹是同级:
![](https://img.haomeiwen.com/i9084896/e3a0ae60fb05973a.png)
2:在build.gradle中 android{} 下添加以下代码:
//适配暗黑模式
sourceSets {
main {
java {
srcDir 'src/main/java'
}
res.srcDirs += 'src/main/res'
res.srcDirs += 'src/main/res-night'
}
}
3:在Application类中添加以下代码:
private Resources mSkinResources = null;
@Override
public Resources getResources() {
if (mSkinResources == null) {
mSkinResources = new SkinResources(this,super.getResources());
}
return mSkinResources;
}
4:SkinResources 类源码:
class SkinResources(context: Context, res: Resources) : Resources(res.assets, res.displayMetrics, res.configuration) {
val contextRef: WeakReference<Context> = WeakReference(context)
override fun getDrawableForDensity(id: Int, density: Int, theme: Theme?): Drawable? {
return super.getDrawableForDensity(resetResIdIfNeed(contextRef.get(), id), density, theme)
}
override fun getColor(id: Int, theme: Theme?): Int {
return super.getColor(resetResIdIfNeed(contextRef.get(), id), theme)
}
override fun getColorStateList(id: Int, theme: Theme?): ColorStateList {
return super.getColorStateList(resetResIdIfNeed(contextRef.get(), id), theme)
}
private fun resetResIdIfNeed(context: Context?, resId: Int): Int {
// 非暗黑无需替换资源 ID
val boolean = SPUtils.getBoolean(context, "mode", false) //默认为白天模式
if (context == null || !boolean)
{
return resId
}
var newResId = resId
val res = context.resources
try {
val resPkg = res.getResourcePackageName(resId)
// 非本包资源无需替换
if (context.packageName != resPkg) return newResId
val resName = res.getResourceEntryName(resId)
val resType = res.getResourceTypeName(resId)
// 获取对应暗黑皮肤的资源 id
val id = res.getIdentifier("${resName}_night", resType, resPkg)
if (id != 0) newResId = id
} finally {
return newResId
}
}
}
5:给 res-night 文件夹中的colors文件添加颜色,具体要映射多少颜色,需要根据项目情况来定,这里举例如下:
res 文件夹中colors中的白色:
<color name="white">#ffffff</color>
在这里应该是:
<color name="white_night">#000000</color>
到此为止链接1中需要做的事情已经做完了,下面是链接2中的步骤:
1:在Application类的onCreate()中添加以下代码:
boolean isNight = SPUtils.getBoolean(this, "mode", false); //默认为白天模式
if (isNight)
{
//这个方法一设置就会全局生效,但是只能作用于xml中,对于代码中动态设置的颜色无效
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
2:在res文件夹下创建values-night文件夹,如下:
![](https://img.haomeiwen.com/i9084896/1ba20662730d4a4b.png)
3:colors文件中颜色对应如下:
<color name="white">#ffffff</color>
在这里应该是:
<color name="white">#000000</color>
到此为止链接2中需要做的事情已经做完了,下面是暗黑模式的开关部分:
val isNight = SPUtils.getBoolean(this, "mode",false)
SPUtils.put(this,"mode",!isNight)
if (!isNight)
{
//这个方法一设置就会全局生效,但是只能作用于xml中,对于代码中动态设置的颜色无效
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}else{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
网友评论