• Android 白天黑夜模式切换适配及引起的Activity销毁重启解决


    目录

    一、白夜模式切换,Activity销毁重启解决:

    二、 暗黑模式适配

     1. 添加依赖:

      2. 复制下面工具类方法直接使用即可:

    3.资源适配:

     4. 适配回调:

    5.切换白夜模式注意事项:


    一、白夜模式切换,Activity销毁重启解决:

            当白夜模式切换时,activity会销毁重新加载,谷歌是希望重新加载Activity可以刷新页面UI,但我的App并没有适配深色模式,这样用户体验就很不好,解决办法就是:

    在AndroidManifest.xml中给Activiyty添加或追加 android:configChanges="uiMode" 属性即可:

     configChanges 参数详解:

     

    二、 暗黑模式适配

     1. 添加依赖:

    1. api 'com.android.support:appcompat-v7:24.1.1' 或者更高版本
    2. 或使用androidx的依赖都可以

      2. 复制下面工具类方法直接使用即可:

    1. /**
    2. * 暗黑模式适配工具类
    3. */
    4. public class DarkModeUtils {
    5. public static final String KEY_MODE = "white_night_mode_sp";
    6. /**
    7. * 在 Application 的 onCreate() 方法中调用
    8. */
    9. public static void init(Application application) {
    10. int nightMode = getNightModel(application);
    11. AppCompatDelegate.setDefaultNightMode(nightMode);
    12. }
    13. /**
    14. * 应用夜间模式
    15. */
    16. public static void applyNightMode(Context context) {
    17. AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
    18. setNightModel(context, AppCompatDelegate.MODE_NIGHT_YES);
    19. }
    20. /**
    21. * 应用日间模式
    22. */
    23. public static void applyDayMode(Context context) {
    24. AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
    25. setNightModel(context, AppCompatDelegate.MODE_NIGHT_NO);
    26. }
    27. /**
    28. * 跟随系统主题时需要动态切换
    29. */
    30. public static void applySystemMode(Context context) {
    31. AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
    32. setNightModel(context, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
    33. }
    34. /**
    35. * 判断App当前是否处于暗黑模式状态
    36. */
    37. public static boolean isDarkMode(Context context) {
    38. int nightMode = getNightModel(context);
    39. if (nightMode == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) {
    40. int applicationUiMode = context.getResources().getConfiguration().uiMode;
    41. int systemMode = applicationUiMode & Configuration.UI_MODE_NIGHT_MASK;
    42. return systemMode == Configuration.UI_MODE_NIGHT_YES;
    43. } else {
    44. return nightMode == AppCompatDelegate.MODE_NIGHT_YES;
    45. }
    46. }
    47. private static int getNightModel(Context context) {
    48. SharedPreferences sp = context.getSharedPreferences(KEY_MODE, Context.MODE_PRIVATE);
    49. return sp.getInt(KEY_MODE, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
    50. }
    51. public static void setNightModel(Context context, int nightMode) {
    52. SharedPreferences sp = context.getSharedPreferences(KEY_MODE, Context.MODE_PRIVATE);
    53. sp.edit().putInt(KEY_MODE, nightMode).apply();
    54. }
    55. }

    3.资源适配:

           对图片和颜色创建暗黑模式的文件夹,切换暗黑模式时系统会自动使用该文件夹下的资源:

     4. 适配回调:

    如果添加或追加了 android:configChanges="uiMode"属性, 在模式切换后会回调Activity的onConfigurationChanged(),建议在BaseActivity中重写该方法,并在里面做相应的适配.

    可以调用上面工具类中的  DarkModeUtils.isDarkMode(this) 方法判断是否是暗黑模式.也可以调用工具类中的方法切换App的白夜模式,注意事项看下面:

    5.切换白夜模式注意事项:

    (1) 在 Application 的 onCreate() 方法中调用 DarkModeUtils.init(this) 初始化工具类;

    (2) 调用 DarkModeUtils.applySystemMode(this) 方法自适应系统白夜模式切换;

    (3) 如果使用的 androidx的依赖直接调用即可.

    (4) 如果使用support依赖需要手动调用Activity的 recreate()方法重建页面或针对页面所有View做不同适配.

    直接调用recreate()方法重建页面示例:

     针对页面每个View去设置白夜模式的示例:

    (5) 具体原因看下面源码:

    androidx版本:

    1. /**
    2. * Sets the default night mode. This is the default value used for all components, but can
    3. * be overridden locally via {@link #setLocalNightMode(int)}.
    4. *
    5. *

      This is the primary method to control the DayNight functionality, since it allows

    6. * the delegates to avoid unnecessary recreations when possible.

    7. *
    8. *

      If this method is called after any host components with attached

    9. * {@link AppCompatDelegate}s have been 'started', a {@code uiMode} configuration change
    10. * will occur in each. This may result in those components being recreated, depending
    11. * on their manifest configuration.

    12. *
    13. *

      Defaults to {@link #MODE_NIGHT_FOLLOW_SYSTEM}.

    14. *
    15. * @see #setLocalNightMode(int)
    16. * @see #getDefaultNightMode()
    17. */
    18. public static void setDefaultNightMode(@NightMode int mode) {
    19. switch (mode) {
    20. case MODE_NIGHT_NO:
    21. case MODE_NIGHT_YES:
    22. case MODE_NIGHT_FOLLOW_SYSTEM:
    23. case MODE_NIGHT_AUTO_TIME:
    24. case MODE_NIGHT_AUTO_BATTERY:
    25. if (sDefaultNightMode != mode) {
    26. sDefaultNightMode = mode;
    27. applyDayNightToActiveDelegates();
    28. }
    29. break;
    30. default:
    31. Log.d(TAG, "setDefaultNightMode() called with an unknown mode");
    32. break;
    33. }
    34. }

    support版本:

    1. public static void setDefaultNightMode(int mode) {
    2. switch(mode) {
    3. case -1:
    4. case 0:
    5. case 1:
    6. case 2:
    7. sDefaultNightMode = mode;
    8. break;
    9. default:
    10. Log.d("AppCompatDelegate", "setDefaultNightMode() called with an unknown mode");
    11. }
    12. }

    对比后可以发现androidx切换暗黑模式后,自己主动调用了applyDayNightToActiveDelegates()方法,使Activity重建。而support上没有,只是赋值。所以support版本上使用需要自己调用Activity的recreate()方法重建。

  • 相关阅读:
    体验昇腾Ascend C 编程语言极简易用的算子开发
    4-egg-TS-通用后端管理注册系统-邮箱验证码
    LeetCode(力扣)77. 组合Python
    vue-element-admin—登录页面添加自定义背景
    Jetpack 之 LiveData 实现事件总线
    获取随机id的api接口
    vivado FFT IP仿真(1)FFT基本知识
    1、Spring简介
    win10重装系统后没声音怎么办?
    iOS Swift数据类型与Data的转换
  • 原文地址:https://blog.csdn.net/zhao8856234/article/details/126578124