前言
Android 6.0以后系统提供了AppCompatDelegate用来实现夜间模式和日间模式的切换,AppCompatDelegate中存在以下几种模式:
AppCompatDelegate.MODE_NIGHT_YES:设置夜间模式
AppCompatDelegate.MODE_NIGHT_NO:设置日间模式
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM:跟随系统设置决定是否设置夜间模式
AppCompatDelegate.MODE_NIGHT_AUTO:根据当前时间自动切换模式
实现夜间模式需要配置两套资源文件而且资源文件的命名要完全一致,后缀带-night的目录对应夜间模式,比如values对应日间模式,values-night对应夜间模式,系统会根据当前的模式自动加载对应的资源文件。
日间模式 | 夜间模式 |
values | values-night |
drawable | drawable-night |
drawable-xhdpi | drawable-night-xhdpi |
mipmap-mdpi | mipmap-night-mdpi |
mipmap-hdpi | mipmap-night-hdpi |
mipmap-xhdpi | mipmap-night-xhdpi |
mipmap-xxhdpi | mipmap-night-xxhdpi |
mipmap-xxxhdpi | mipmap-night-xxxhdpi |
设置主题
首先设置应用主题为DayNight模式,如Theme.AppCompat.DayNight.DarkActionBar或者Theme.MaterialComponents.DayNight.DarkActionBar,如下:
<style name="Theme.NightModeDemo" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
AndroidManifest配置application的android:theme:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.NightModeDemo">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
顺便说一下,现在在Android Studio 4.0以上新建的project已经默认主题样式为Theme.MaterialComponents.DayNight.DarkActionBar,同时已经配置了日间和夜间两套主题文件theme.xml。
配置颜色
src/main/res目录下新建values-night目录,在该目录下新建colors.xml,然后配置同一个颜色值在values/colors.xml和values-night/colors.xml、也就是日间模式和夜间模式下对应的取值,注意颜色值的命名要完全一样。
values/colors.xml取值如下:
<resources>
<color name="black">#000000</color>
<color name="white">#FFFFFF</color>
<color name="window_background">#FFFFFF</color>
</resources>
values-night/colors.xml取值如下:
<resources>
<color name="black">#FFFFFF</color>
<color name="white">#000000</color>
<color name="window_background">#000000</color>
</resources>
配置图片
src/main/res目录下新建mipmap-night-xhdpi目录,在mipmap-night-xhdpi和mipmap-xhdpi目录分别配置夜间和日间模式的两套图片,注意两张图片的命名要完全一样。以ic_pic为例,项目结构如下:
使用
在布局文件中使用配置好的颜色和图片:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/window_background"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/modeTv"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@drawable/shape_btn_bg"
android:gravity="center"
android:textColor="@color/black"
android:textSize="15sp"
tools:text="白天模式" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:src="@mipmap/ic_pic" />
</LinearLayout>
其中shape_btn_bg如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="6dp" />
<stroke
android:width="2dp"
android:color="@color/black" />
<solid android:color="@color/white" />
</shape>
在代码中使用:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initMode()
modeTv.setOnClickListener {
switchMode()
}
}
private fun initMode() {
when (AppCompatDelegate.getDefaultNightMode()) {
AppCompatDelegate.MODE_NIGHT_NO -> {
modeTv.text = "日间模式"
}
AppCompatDelegate.MODE_NIGHT_YES -> {
modeTv.text = "夜间模式"
}
else -> {
modeTv.text = "日间模式"
}
}
}
//切换夜间模式
private fun switchMode() {
when (AppCompatDelegate.getDefaultNightMode()) {
AppCompatDelegate.MODE_NIGHT_NO -> { //当前为日间模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) //切换为夜间模式
}
AppCompatDelegate.MODE_NIGHT_YES -> { //当前为夜间模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) //切换为日间间模式
}
else -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) //切换为夜间模式
}
}
recreate() //需要调用该方法才能生效
}
}
最后看一下效果:
源码地址
————————————————
版权声明:本文为CSDN博主「xuzhb24」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xuzhb_blog/article/details/121415362