Android 10系统增加了暗黑模式,但是并没有像IOS那样强制适配。暗黑模式下可大幅减少耗电量。而且在晚上使用手机的情况下可以有效的保护视力,减少对眼睛的伤害。这个可以在手机的“设置->显示和亮度->深色模式”进行切换。(以华为手机为例)
暗黑模式一般由两种适配方法,下面我们就一起来了解Android 10系统的暗黑模式的两种适配方法。(注意:这里前提是要把项目的targetSdkVersion 设置为29 )
手动适配相对来说比较简单,就是类似于之前的屏幕适配。比如适配颜色的话,就在res 下新建 values-night目录,创建对应的colors.xml文件。如果适配图片的话,就创建对应的 drawable-night目录。
下面我们就一起来尝试一下:
写一个布局,里面有图片和文字:
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<ImageView
android:id="@+id/iv_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:src="@drawable/icon_pause"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="文字颜色"
android:textColor="@color/color_content"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_image" />
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/bt_paly"
android:layout_width="200dp"
android:layout_height="50dp"
android:layout_marginTop="20dp"
android:text="播放"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_text" />
<Button
android:id="@+id/bt_pause"
android:layout_width="200dp"
android:layout_height="50dp"
android:layout_marginTop="20dp"
android:text="暂停"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/bt_paly" />
</androidx.constraintlayout.widget.ConstraintLayout>
针对适配图片:在res文件夹下创建了两个文件夹,drawable-xhdpi用于放置白天模式下的图片,和drawable-night-xhdpi用于放置黑夜模式下的图片。
针对适配文字颜色:在values下有一个colors.xml文件用于书写白天模式下的颜色值,在res文件夹下创建一个values-night文件夹,里面同样创建一个colors.xml文件,用于书写黑夜模式下的颜色值。
<color name="color_content">#FF0000</color>
<color name="color_content">#FFFFFF</color>
运行之后,看一下效果:
好了,手动适配的方式就介绍到这里,手动适配其实说白了就是资源适配。
Android10 提供了一种自动适配的方式,即Fork Dark。应用可以通过设置 android:forceDarkAllowed=“true”,来实现暗黑模式的自动适配。
注意:如果使用Dark Theme主题(例如Theme.Material),则系统不会应用 Force Dark。同样,如果应用的主题继承自 DayNight 主题(例如Theme.AppCompat.DayNight),则系统不会应用 Force Dark。
如果使用的是 DayNight 或 Dark Theme 主题,则设置forceDarkAllowed 不生效。
此外还可以通过setForceDarkAllowed(boolean) 在特定的View上控制 Force Dark。
例:在res文件夹下,新建一个values-29的文件夹,里面新建一个styles.xml的文件,里面写上在暗黑模式下要设置的Theme。
这时候,在系统设置里面,把系统切换为暗黑模式,那么当前App就会使用values-29文件夹下的styles.xml文件里面的AppTheme主题。但是这里要注意的是,因为主题是:
parent="Theme.AppCompat.DayNight.DarkActionBar"
所以,这里的
<item name="android:forceDarkAllowed">false</item>
不管设置为true或者false,forceDarkAllowed都不会生效。
如果主题设置的是:
parent="Theme.AppCompat.Light.DarkActionBar"
那么当forceDarkAllowed为false的时候,显示白天模式,当forceDarkAllowed为true的时候,显示暗黑模式。此时,forceDarkAllowed的设置是生效的。
<item name="android:forceDarkAllowed">false</item>
<item name="android:forceDarkAllowed">true</item>
此外,我们还可以通过 AppCompatDelegate.setDefaultNightMode(@NightMode int mode)方法手动切换主题:
public static class ThemeHelper {
public static final String LIGHT_MODE = "light";
public static final String DARK_MODE = "dark";
public static final String DEFAULT_MODE = "default";
public static void applyTheme(@NonNull String themePref) {
switch (themePref) {
case LIGHT_MODE: {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
break;
}
case DARK_MODE: {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
break;
}
default: {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
}
break;
}
}
}
}
参数mode有以下几种模式:
浅色 - MODE_NIGHT_NO
深色 - MODE_NIGHT_YES
由省电模式设置 - MODE_NIGHT_AUTO_BATTERY
系统默认 - MODE_NIGHT_FOLLOW_SYSTEM
我们还可以监听到暗黑的主题是否开启
(1)在清单文件中给对应的Activity配置 android:configChanges=“uiMode”:
<activity android:name=".MainActivity"
android:configChanges="uiMode">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
(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;
}
}
这时,可以通过系统的设置切换暗黑模式的关闭和开启,查看下输出的Log。
我们还可以判断深色模式是否开启:
public static boolean isNightMode(Context context) {
int currentNightMode = context.getResources().getConfiguration().uiMode &
Configuration.UI_MODE_NIGHT_MASK;
return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
}
Android 10新加了暗黑模式,我们可以通过Force Dark来自动适配,然后再通过手动适配来进行图片资源以及颜色等的适配。