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来自动适配,然后再通过手动适配来进行图片资源以及颜色等的适配。
下一个:java多线程学习2,线程的属性