深色模式,也称为夜间模式或黑暗模式,具有比常规模式更低的亮度和更高的对比度。在晚上或灰暗的环境中使用深色模式可以减少眼睛疲劳,有利于保护眼睛健康。此外,深色模式还可以节省电量和延长电池寿命。因此,实现Android应用的深色模式已经是一个很有必要的功能。
一、Android的深色模式
Android 10 (API Level 29)中引入了深色主题(Dark Theme)API,让 Android 应用程序能够在日间模式和夜间模式之间进行切换,同时还支持不根据时间自动切换模式等功能。在深色模式下,Android 会应用适当的颜色主题来替换 APP 中浅色的背景和前景色。对于 Android 应用程序,只需在 res/values 下建立一个对应的 dark 文件夹,在里面建立相同的 XML 文件,然后更改 AndroidManifest.xml 中的 android:theme.
二、应用的深色模式实现
深色模式可以通过两种方式实现:手动设置和跟随系统。不同的应用程序有不同的实现方式,但大致思路都相同,通过检测系统主题的更改来触发相应的样式处理。下面提供一个简单的示例,演示如何使用 AppCompat 库实现应用的深色模式。
1. 设置主题
在 styles.xml 文件中定义一个名为 AppTheme 的主题,并继承自 AppCompat 的日间主题。然后在 styles.xml (night) 文件中定义名为 AppDarkTheme 的主题,并继承自 AppCompat 的深色主题。这样,我们就有了日间和深色两个主题。例如:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/background_light</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorPrimary">@color/textColorPrimaryLight</item>
<item name="android:textColorSecondary">@color/textColorSecondaryLight</item>
</style>
<style name="AppDarkTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">@color/background_dark</item>
<item name="colorPrimary">@color/colorPrimaryDark</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorPrimary">@color/textColorPrimaryDark</item>
<item name="android:textColorSecondary">@color/textColorSecondaryDark</item>
</style>
</resources>
2. 实现深色模式的开关按钮
在应用的设置界面添加一个深色模式的开关按钮。可以使用 Switch 按钮,示例如下:
<Switch
android:id="@+id/switchDarkMode"
android:text="@string/switch_dark_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorBlack"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
3. 触发深色模式
使用以下代码控制应用程序的深色模式:
switchDarkMode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//检测当前系统主题
int currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
switch (currentNightMode) {
case Configuration.UI_MODE_NIGHT_NO:
// 切换到深色模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
break;
case Configuration.UI_MODE_NIGHT_YES:
// 切换到日间模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
break;
}
// 重启该Activity以生效
recreate();
}
});
三、结语
深色模式可以给用户带来更好的使用体验和更低的眼睛疲劳。开发人员应该考虑支持深色模式,并实现相应的切换机制。随着 Android Q 中的深色主题 API 的出现,实现 Android 应用的深色模式变得更为容易。希望这篇文章可以为你实现深色模式提供一些帮助。
完整的代码示例: styles.xml:<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/background_light</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorPrimary">@color/textColorPrimaryLight</item>
<item name="android:textColorSecondary">@color/textColorSecondaryLight</item>
</style>
</resources>
styles.xml (night):
<resources>
<style name="AppDarkTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">@color/background_dark</item>
<item name="colorPrimary">@color/colorPrimaryDark</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorPrimary">@color/textColorPrimaryDark</item>
<item name="android:textColorSecondary">@color/textColorSecondaryDark</item>
</style>
</resources>
主界面布局 activity_main.xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"/>
<TextView
android:text="@string/hello_world"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"/>
<Switch
android:id="@+id/switchDarkMode"
android:text="@string/switch_dark_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorBlack"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</LinearLayout>
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private Switch switchDarkMode;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
switchDarkMode = findViewById(R.id.switchDarkMode);
switchDarkMode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//检测当前系统主题
int currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
switch (currentNightMode) {
case Configuration.UI_MODE_NIGHT_NO:
// 切换到深色模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
break;
case Configuration.UI_MODE_NIGHT_YES:
// 切换到日间模式
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
break;
}
// 重启该Activity以生效
recreate();
}
});
}
}