Android Q 暗黑模式

1、Force Dark
一种能让应用程序快速适配深色主题,Force Dark的工作原理是系统会分析浅色主题应用下的每一层View,并且在这些View绘制到屏幕之前,自动将它们的颜色转换成更加适合深色主题的颜色。注意,只有原本使用浅色主题的应用才能使用这种方式,如果你的应用原本使用的就是深色主题,Force Dark将不会起作用。
右击res目录 -> New -> Directory,创建一个values-v29目录,然后右击values-v29目录 -> New -> Values resource file,创建一个styles.xml文件。接着对这个文件进行编写,代码如下所示:

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:forceDarkAllowed">true</item>
    </style>
</resources>

除了android:forceDarkAllowed属性之外,其他的内容都是从之前的styles.xml文件中复制过来的。这里给AppTheme主题增加了android:forceDarkAllowed属性并设置为true,说明现在我们是允许系统使用Force Dark将应用强制转换成深色主题的。另外,values-v29目录是只有Android 10.0及以上的系统才会去读取的,因此这是一种系统差异型编程的实现方式。
2、values-night适配
(1)将AppTheme的parent主题指定成了Theme.AppCompat.DayNight.NoActionBar ,这是一种DayNight主题。因此,在普通情况下MaterialTest项目仍然会使用浅色主题,和之前并没有什么区别,但是一旦用户在系统设置中开启了深色主题,MaterialTest项目就会自动使用相应的深色主题
(2)创建values-night目录,增加color.xml
color.xml中的颜色命名与values目录下的color.xml中的命名相同,在普通情况下,系统仍然会读取values/colors.xml文件中的颜色值,而一旦用户开启了深色主题,系统就会去读取values-night/colors.xml文件中的颜色值了。
如果适配图片的话,就创建对应的 drawable-night目录
3、切换主题
黑暗模式和正常模式,无非就是两种主题间的切换(主要是各种背景色,字体颜色和Icon)。因此我们只需要定义两套不同的主题,根据是否是黑暗模式进行主题的切换即可
(1)判断当前是否处于黑暗模式:用于启动时还在不同的主题

//检查当前系统是否已开启暗黑模式
    public static boolean getDarkModeStatus(Context context) {
        int mode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
        return mode == Configuration.UI_MODE_NIGHT_YES;
    }

(2)定义两套主题(正常模式和黑暗模式):即在style文件下自定义两个style,但是必须指定parent为‘Theme.AppCompat.DayNight.DarkActionBar’,如下所示:

//正常模式下的主题
 <style name="main_theme_light" parent="Theme.AppCompat.DayNight.DarkActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="main_text_color">@color/main_text_color_light</item>
        <item name="main_bg_color">@color/main_bg_color_light</item>
    </style>

//黑暗模式下的主题
 <style name="main_theme_dark" parent="Theme.AppCompat.DayNight.DarkActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="main_text_color">@color/main_text_color_dark</item>
        <item name="main_bg_color">@color/main_bg_color_dark</item>
    </style>

(3)找出适配黑暗模式需要的属性(主要是颜色属性:背景色、字体颜色和Icon颜色等并给属性赋值),类似如下定义:

 <!--    主要字体颜色-->
    <attr name="main_text_color" format="color" />
 <!--    主要背景颜色-->    
    <attr name="main_bg_color" format="color" />


        //不同模式下的颜色属性值
        <color name="main_text_color_light">#000000</color>
    <color name="main_text_color_dark">#ffffff</color>
    <color name="main_bg_color_light">#ffffff</color>
    <color name="main_bg_color_dark">#000000</color>

(4)在activity和xml中引用我们自定义的属性:
//在xml文件中使用我们自定义属性

<androidx.constraintlayout.widget.ConstraintLayout 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:background="?attr/main_bg_color">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textColor="?attr/main_text_color"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

(5)在BaseActivity中切换不同的主题,才能使我们自定义的属性生效,必须在setContentView()方法前设置:
//在BaseActivity中切换不同的主题,才能使我们自定义的属性生效,必须在setContentView()方法前设置:

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        if (getDarkModeStatus(this)) {
            setTheme(R.style.main_theme_dark);
        }else {
            setTheme(R.style.main_theme_light);
        }
        setContentView(R.layout.activity_main)
     }

//为达到更好的适配效果,可在xml文件的activity节点下加入如下属性:
android:configChanges="uiMode

tips:
1、监听深色主题是否开启
1)在清单文件中给对应的Activity配置 android:configChanges=“uiMode”
2)在onConfigurationChanged方法中获取:

@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        int currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
        switch (currentNightMode) {
            case Configuration.UI_MODE_NIGHT_NO:
                Log.e("=======","=====关闭夜间模式====");
                // 关闭
                break;
            case Configuration.UI_MODE_NIGHT_YES:
                Log.e("=======","=====开启夜间模式====");
                // 开启
                break;
            default:
                break;
        }
}

2、判断深色主题是否开启

public static boolean isNightMode(Context context) {
        int currentNightMode = context.getResources().getConfiguration().uiMode &
                Configuration.UI_MODE_NIGHT_MASK;
        return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
}

3、可以通过Force Dark来自动适配,然后再通过values-night适配来进行图片资源以及颜色等的适配。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值