IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【Android】日夜间模式填坑记 -> 正文阅读

[移动开发]【Android】日夜间模式填坑记

简单使用

设置夜间模式的类是AppCompatDelegate。

设置全局夜间模式

public static void setDefaultNightMode(@NightMode int mode) {

给页面单独设置夜间模式

@RequiresApi(17)
public abstract void setLocalNightMode(@NightMode int mode);

在Activity中调用,注意,要在setContentView之前:

getDelegate.setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES)

配置夜间模式资源

在资源文件夹中创建对应的夜间模式文件夹,后缀为-night。例如:values文件夹下的colors.xml,此时我们想给 <color name="bg">#FFFFFFFF</color>,配置对应的夜间模式色值,先创建values-night文件夹,然后在文件夹下创建文件colors.xml,在xml文件中写入<color name="bg">#FF000000</color>。此时夜间模式的资源就配置好了,在布局文件中使用即可,系统会根据代码的设置,读取对应的色值。

关于页面重建recreate

当我们给页面单独设置模式时,Activity会调用recreate方法,重新创建页面。重建之前,Activity的生命周期也会执行一遍。

private boolean updateForNightMode(@ApplyableNightMode final int mode,
            final boolean allowRecreation) {
        boolean handled = false;

        final Configuration overrideConfig =
                createOverrideConfigurationForDayNight(mContext, mode, null);

        final boolean activityHandlingUiMode = isActivityManifestHandlingUiMode();
        final int currentNightMode = mContext.getResources().getConfiguration().uiMode
                & Configuration.UI_MODE_NIGHT_MASK;
        final int newNightMode = overrideConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;

        if (currentNightMode != newNightMode
                && allowRecreation
                && !activityHandlingUiMode
                && mBaseContextAttached
                && (sCanReturnDifferentContext || mCreated)
                && mHost instanceof Activity
                && !((Activity) mHost).isChild()) {
//			调用重建
            ActivityCompat.recreate((Activity) mHost);
            handled = true;
        }

        if (!handled && currentNightMode != newNightMode) {
            updateResourcesConfigurationForNightMode(newNightMode, activityHandlingUiMode, null);
            handled = true;
        }

        if (handled && mHost instanceof AppCompatActivity) {
            ((AppCompatActivity) mHost).onNightModeChanged(mode);
        }

        return handled;
    }

因此,我们看到页面出现后马上消失了,然后再次出现,会闪一下。为了避免这种情况,我们可以在Manifest中为Activity配置configChanges

<activity
    android:configChanges="uiMode"
/>

弹窗类Activity导致的前一个Activity颜色混乱

有时候我们会启动这样一个Acitivty,UI效果类似于一个dialog,并且需要在代码中单独设置了夜间模式。
一般我们会这样给Activity设置主题:

<activity
    android:theme="@style/dialog_activity" 
/>
<style name="dialog_activity" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="android:windowNoTitle">true</item>
    <item name="colorPrimaryDark">@android:color/transparent</item>
    <!--设置动画,在这里使用让它继承系统的Animation.Dialog-->
    <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <!--背景透明-->
    <item name="android:backgroundDimEnabled">true</item>
    <!-- 半透明 -->
    <item name="android:windowIsTranslucent">true</item>
</style>

当关闭掉弹窗,回到前一个Activity时,Activity的部分UI会使用夜间模式,UI中存在RecyclerView时,比较容易复现。

目前不清楚出现这种问题的原因是什么,以下仅为猜测。因为window的背景是透明的,前一个Activity的部分UI对用户可见,那么当前一个Acitivty使用日间模式,dialog使用夜间模式时,为了保证用户的体验一致,即dialog和背景Activity都使用夜间模式,系统会暂时给背景Activity设置夜间模式。测试中,只要背景不透明,看不到背景Activity的UI,就不会发生颜色混乱。

解决办法

尝试了多种办法后,最终放弃了给弹窗类Activity单独设置夜间模式。取而代之,使用了主题色。

自定义一部分属性:

    <attr name="dialog_st_text_lv1" format="color|reference"/>
    <attr name="dialog_main_bg" format="color|reference"/>
    <attr name="dialog_title_color" format="color|reference"/>
    <attr name="dialog_title_bg" format="reference"/>
    <attr name="dialog_edit_bg" format="reference"/>
    <attr name="dialig_st_divider_lv1" format="reference|color"/>

然后添加日间模式主题,设置对应的资源:

 <style name="dialog_activity.light">
     <item name="dialog_main_bg">#ffffff</item>
     <item name="dialog_st_text_lv1">#ff111111</item>
     <item name="dialog_title_color">#333333</item>
     <item name="dialog_title_bg">@drawable/bg_dialog_title_light</item>
     <item name="dialog_edit_bg">@drawable/edittext_bg_light</item>
     <item name="dialig_st_divider_lv1">#fff2f2f2</item>
 </style>

添加夜间模式主题,设置对应的资源:

<style name="dialog_activity.dark">
    <item name="dialog_main_bg">#191b27</item>
    <item name="dialog_st_text_lv1">#ffe4e4e4</item>
    <item name="dialog_title_color">#cfd1dc</item>
    <item name="dialog_title_bg">@drawable/bg_dialog_title_dark</item>
    <item name="dialog_edit_bg">@drawable/edittext_bg_dark</item>
    <item name="dialig_st_divider_lv1">#ff07080b</item>
</style>

最后在layout中调用:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="wrap_content"
    tools:theme="@style/dialog_activity.light">

     <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/dialog_title_bg">
     </FrameLayout>

</RelativeLayout>

不要忘记在代码中设置主题:

@Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {Bundle bundle = getIntent().getExtras();
      if (IS_NIGHT_MODE) {
          setTheme(R.style.dialog_activity_light);
      }else {
          setTheme(R.style.dialog_activity_dark);
      }
     super.onCreate(savedInstanceState);
 }

其他疑问

当一个弹窗类Activity,没有设置android:configChanges="uiMode",理所当然会进行recreate,但是仅限于第一次出现。如果再次弹窗就不会recreate,如果前一个Activity执行了onPause,再弹窗还是会出现一次recreate,不知道是不是有缓存

参考:

AppCompatDelegate API

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:27:25  更:2022-09-13 11:31:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 5:25:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码