Android 深色模式适配总结

2022年12月27日12:25:21

Android 深色模式适配总结

前言

iOS13推出暗黑模式,既然苹果实现了暗黑模式,那么安卓肯定不能落下啊,所以在安卓10(Q API级别29)中支持了暗黑模式,不过官方的叫法为Dark theme。

适配流程

主题设置

为了支持Dark主题,必须将应用的主题设置为继承自DayNight系列的主题。

Theme.MaterialComponents.DayNight.DarkActionBar
或:
Theme.AppCompat.DayNight

资源文件处理

Android 深色模式适配总结

需要在对应的资源文件中添加night文件夹,这里存放的就是深色模式相关的资源,也就是说需要准备2套资源。

如:

values strings.xml和values-night strings.xml

Android 深色模式适配总结

values-colors.xml和values-night strings.xml

Android 深色模式适配总结

代码相关

XML布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="@color/color_background"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:layout_marginTop="10dp"
        android:scaleType="fitXY"
        android:src="@drawable/light" />

    <ImageView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/frame_shape"
        android:src="@drawable/ic_daynight"
        app:tint="@color/color_daynight" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="@string/day_night"
        android:textColor="@color/color_daynight"
        android:textSize="18sp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnLight"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="浅色模式" />

        <Button
            android:id="@+id/btnDark"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="10dp"
            android:text="深色模式" />

        <Button
            android:id="@+id/btnSystem"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="跟随系统" />
    </LinearLayout>    
</LinearLayout>

代码:

object ThemeUtils {
    /**
     * 是否深色主题
     */
    fun isDarkTheme(context: Context): Boolean {
        val flag = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
        return flag == Configuration.UI_MODE_NIGHT_YES
    }
}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.e("TAG", "Activity onCreate()")
        initView()
    }

    private fun initView() {
        //手动切换深色模式
        btnLight.setOnClickListener {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
        }
        btnDark.setOnClickListener {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
        }
        btnSystem.setOnClickListener {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
        }
    }

    override fun onStart() {
        super.onStart()
        if (ThemeUtils.isDarkTheme(this)) {
            imageView.setImageResource(R.drawable.dark)
        } else {
            imageView.setImageResource(R.drawable.light)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.e("TAG", "Activity onDestroy()")
    }
}

效果:

Android 深色模式适配总结

配置变更问题

当切换深色模式时,Activity就会重新加载,重走生命周期流程。

为了避免界面重新加载,可以在AndroidManifest.xml文件中设置Activity的android:configChanges="uiMode"。当配置发生变化时,可以通过onConfigurationChanged()方法监听当前应用是什么模式。

Activity#onConfigurationChanged()

//监听系统深色模式切换
override fun onConfigurationChanged(newConfig: Configuration) {
    Log.e("TAG", "onConfigurationChanged:")
    super.onConfigurationChanged(newConfig)
    val currentNightMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
    when (currentNightMode) {
        Configuration.UI_MODE_NIGHT_NO -> {
            // 夜间模式未启用,我们正在使用浅色主题
            textView.setText("当前浅色模式")
        }
        Configuration.UI_MODE_NIGHT_YES -> {
            // 夜间模式启用,我们使用的是深色主题
            textView.setText("当前深色模式")
        }
    }
}

代码下载

  • 作者:xiangxiongfly915
  • 原文链接:https://blog.csdn.net/qq_14876133/article/details/127903857
    更新时间:2022年12月27日12:25:21 ,共 3564 字。