iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android夜间模式最佳实践
  • 655
分享到

Android夜间模式最佳实践

Android 2022-06-06 09:06:27 655人浏览 薄情痞子
摘要

由于Android的设置中并没有夜间模式的选项,对于喜欢睡前玩手机的用户,只能简单的调节手机屏幕亮度来改善体验。目前越来越多的应用开始把夜间模式加到自家应用中,没准不久Goog

由于Android的设置中并没有夜间模式的选项,对于喜欢睡前玩手机的用户,只能简单的调节手机屏幕亮度来改善体验。目前越来越多的应用开始把夜间模式加到自家应用中,没准不久Google也会把这项功能添加到Android系统中吧。

业内关于夜间模式的实现,有两种主流方案,各有其利弊,我较为推崇第三种方案:

1、通过切换theme来实现夜间模式。
2、通过资源id映射的方式来实现夜间模式。
3、通过修改uiMode来切换夜间模式。

值得一提的是,上面提到的几种方案,都是资源内嵌在Apk中的方案,像新浪微博那种需要通过下载方式实现的夜间模式方案,网上有很多介绍,这里不去讨论。

下面简要描述下几种方案的实现原理:

一、通过切换theme来实现夜间模式

首先在attrs.xml中,为需要随theme变化的内容定义属性


<?xml version="1.0" encoding="utf-8"?>
<resources>
  <attr name="textColor" fORMat="color|reference" />
  <attr name="mainBackground" format="color|reference" />
</resources>

其次在不同的theme中,对属性设置不同的值,在styles.xml中定义theme如下


<?xml version="1.0" encoding="utf-8"?>
<resources>
  <!-- 默认 -->
  <style name="ThemeDefault" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="mainBackground">#ffffff</item>
    <item name="textColor">#000000</item>
  </style>
  <!-- 夜间 -->
  <style name="ThemeNight" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="mainBackground">#000000</item>
    <item name="textColor">#ffffff</item>
  </style>
</resources>

在布局文件中使用对应的值,通过?attr/属性名,来获取不同theme对应的值。


<LinearLayout xmlns:android="Http://schemas.android.com/apk/res/android"
  android="@+id/main_screen"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  android:background="?attr/mainBackground">
  <Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="改变Theme"
    android:onClick="changeTheme"
    android:textColor="?attr/textColor"/>
</LinearLayout>

在Activity中调用如下changeTheme方法,其中isNightMode为一个全局变量用来标记当前是否为夜间模式,在设置完theme后,还需要调用restartActivity或者setContentView重新刷新UI。


public void changeTheme() {
  if (isNightMode) {
    setTheme(R.style.ThemeDefault);
    isNightMode = false;
  } else {
    setTheme(R.style.ThemeNight);
    isNightMode = true;
  }
  setContentView(R.layout.activity_main);
}

到此即完成了一个夜间模式的简单实现,包括Google自家在内的很多应用都是采用此种方式实现夜间模式的,这应该也是Android官方推荐的方式。

但这种方式有一些不足,规模较大的应用,需要随theme变化的属性会很多,都需要逐一定义,有点麻烦,另外一个缺点是要使得新theme生效,一般需要restartActivity来切换UI,会导致切换主题时界面闪烁。

不过也可以通过调用如下updateTheme方法,只更新需要更新的部分,规避闪烁问题,只是需要写上一堆updateTheme方法。


private void updateTheme() {
  TypedValue typedValue = new TypedValue();
  Resources.Theme theme = getTheme();
  theme.resolveAttribute(R.attr.textColor, typedValue, true);
  findViewById(R.id.button).setBackgroundColor(typedValue.data);
  theme.resolveAttribute(R.attr.mainBackground, typedValue, true);
  findViewById(R.id.main_screen).setBackgroundColor(typedValue.data);
}

二、通过资源id映射的方式实现夜间模式

通过id获取资源时,先将其转换为夜间模式对应id,再通过Resources来获取对应的资源。


public static Drawable getDrawable(Context context, int id) {
  return context.getResources().getDrawable(getResId(id));
}
public static int getResId(int defaultResId) {
  if (!isNightMode()) {
    return defaultResId;
  }
  if (sResourceMap == null) {
    buildResourceMap();
  }
  int themedResId = sResourceMap.get(defaultResId);
  return themedResId == 0 ? defaultResId : themedResId;
}

这里是通过HashMap将白天模式的resId和夜间模式的resId来一一对应起来的。


private static void buildResourceMap() {
  sResourceMap = new SparseIntArray();
  sResourceMap.put(R.drawable.common_background, R.drawable.common_background_night);
  // ...
}

这个方案简单粗暴,麻烦的地方和第一种方案一样:每次添加资源都需要建立映射关系,刷新UI的方式也与第一种方案类似,貌似今日头条,网易新闻客户端等主流新闻阅读应用都是通过这种方式实现的夜间模式。

三、通过修改uiMode来切换夜间模式

首先将获取资源的地方统一起来,使用Application对应的Resources,在Application的onCreate中调用ResourcesManager的init方法将其初始化。


public static void init(Context context) {
  sRes = context.getResources();
}


切换夜间模式时,通过更新uiMode来更新Resources的配置,系统会根据其uiMode读取对应night下的资源,同时在res中给夜间模式的资源添加-night后缀,比如values-night,drawable-night。


public static void updateNightMode(boolean on) {
  DisplayMetrics dm = sRes.getDisplayMetrics();
  Configuration config = sRes.getConfiguration();
  config.uiMode &= ~Configuration.UI_MODE_NIGHT_MASK;
  config.uiMode |= on ? Configuration.UI_MODE_NIGHT_YES : Configuration.UI_MODE_NIGHT_NO;
  sRes.updateConfiguration(config, dm);
}

至于Android的资源读取,我们可以参考老罗的博客《Android应用程序资源的查找过程》,分析看看资源是怎么被精准找到的。这种方法相对前两种的好处就是资源添加非常简单清晰,但是UI上的更新还是无法做到非常顺滑的切换。

我是怎么找到第三种方案的?

在Android开发文档中搜索night发现如下,可以通过UiModeManager来实现

night: Night time
notnight: Day time
Added in api level 8.

This can change during the life of your application if night mode is left in auto mode (default), in which case the mode changes based on the time of day. You can enable or disable this mode using UiModeManager. See Handling Runtime Changes for information about how this affects your application during runtime.

不幸的是必须在驾驶模式下才有效,那是不是打开驾驶模式再设置呢,实际上是不可行的,驾驶模式下系统UI有变动,这样是不可取的。



public void setNightMode(int mode)

源码开始看起,UiModeManagerService.java的setNightMode方法中:


if (isDoingNightModeLocked() && mNightMode != mode) {
  Settings.Secure.putInt(getContext().getContentResolver(), Settings.Secure.UI_NIGHT_MODE, mode);
  mNightMode = mode;
  updateLocked(0, 0);
}
boolean isDoingNightModeLocked() {
  return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
}

在 isDoingNightModeLocked中判断了DockState和mCardMode的状态,如果满足条件实际上只修改了mNightMode的值,继续跟踪updateLocked方法,可以看到在updateConfigurationLocked中更新了Configuration的uiMode。

让我们转向Configuration的uiMode的描述:



public int uiMode;

uiMode为public可以直接设置,既然UiModeManager设置nightMode只改了Configuration的uiMode,那我们是不是可以直接改其uiMode呢?

实际上只需要上面一小段代码就可以实现了,但如果不去查看UiModeManager的夜间模式的实现,不会想到只需要更新Configuration的uiMode就可以了。

您可能感兴趣的文章:android基础教程之夜间模式实现示例Android实现日夜间模式的深入理解Android 实现夜间模式的快速简单方法实例详解三行Android代码实现白天夜间模式流畅切换Android主题切换之探究白天和夜间模式Android实现夜间模式切换功能实现代码Android 夜间模式的实现代码示例Android编程实现夜间模式的方法小结


--结束END--

本文标题: Android夜间模式最佳实践

本文链接: https://www.lsjlt.com/news/25677.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android夜间模式最佳实践
    由于Android的设置中并没有夜间模式的选项,对于喜欢睡前玩手机的用户,只能简单的调节手机屏幕亮度来改善体验。目前越来越多的应用开始把夜间模式加到自家应用中,没准不久goog...
    99+
    2022-06-06
    Android
  • android夜间模式如何实现
    要实现Android夜间模式,可以按照以下步骤操作:1. 创建不同的主题资源:在`res/values/`目录下创建一个`theme...
    99+
    2023-09-08
    android
  • Android 夜间模式的实现代码示例
    夜间模式实现 所谓的夜间模式,就是能够根据不同的设定,呈现不同风格的界面给用户,而且晚上看着不伤眼睛,实现方式也就是所谓的换肤(主题切换)。对于夜间模式的实现网上流传了很多种...
    99+
    2022-06-06
    示例 Android
  • Android实现日夜间模式的深入理解
    在本篇文章中给出了三种实现日间/夜间模式切换的方案,三种方案综合起来可能导致文章的篇幅过长,请耐心阅读。     1、使用 setTheme 的方...
    99+
    2022-06-06
    Android
  • 如何在Android应用中实现夜间模式
    如何在Android应用中实现夜间模式?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。夜间模式实现所谓的夜间模式,就是能够根据不同的设定,呈现不同风格的界面给用户,而且晚上看...
    99+
    2023-05-31
    android roi
  • android基础教程之夜间模式实现示例
    代码如下:package org.david.dayandnightdemo.cor; import android.os.Bundle;import android.app...
    99+
    2022-06-06
    程之 示例 教程 Android
  • Android实现夜间模式切换功能实现代码
    现在很多App都有夜间模式,特别是阅读类的App,夜间模式现在已经是阅读类App的标配了,事实上,日间模式与夜间模式就是给App定义并应用两套不同颜色的主题,用户可以自动或者手...
    99+
    2022-06-06
    Android
  • Android显示富文本+夜间深色模式
    目录前言方案一:存在问题:方法二:富文本内容:演示效果:总结前言 在工作中有遇到这样的需求,需要把hmtl的富文本内容,进行深色模式适配。原先的富文本内容是在直接在webview上进...
    99+
    2022-11-12
  • Android异常处理最佳实践
    一个好的app 异常处理机制 我认为应该至少包含以下几个功能: 1.能把错误信息上传到服务器  让开发者可以持续改进app 2.错误信息至少应该包含 是否在主进程 是...
    99+
    2022-06-06
    Android
  • Golang Facade模式与快速开发的最佳实践
    Golang中的Facade模式是一种结构型设计模式,用于提供一个简化的接口,以便客户端可以更轻松地使用复杂的子系统。它通过将子系统...
    99+
    2023-10-08
    Golang
  • Golang Facade模式的灵活应用与最佳实践
    Golang中的Facade模式可以用于将复杂的子系统封装起来,提供一个简单的接口供客户端使用。这个模式可以提供灵活的应用,并且有一...
    99+
    2023-10-10
    Golang
  • Android 实现夜间模式的快速简单方法实例详解
    ChangeMode 项目地址:ChangeMode Implementation of night mode for Android. 用最简单的方式实现夜间模式,支持Lis...
    99+
    2022-06-06
    方法 Android
  • 三行Android代码实现白天夜间模式流畅切换
    Usage xml android:background= ?attr/zzbackground app:backgroundAttr= zzbackground /...
    99+
    2022-06-06
    Android
  • 选择云服务器配置模式的最佳实践
    1. 了解云服务器配置模式 在选择云服务器配置模式之前,我们需要了解一些基本概念。云服务器配置模式通常分为三种:共享型、独享型和混合型。 共享型:多个用户共享同一台物理服务器的资源,适用于小型网站和应用。 独享型:一台物理服务器只分配给...
    99+
    2023-10-27
    服务器配置 模式
  • Android主题切换之探究白天和夜间模式
    智能手机的迅速普及,大大的丰富了我们的娱乐生活。现在大家都喜欢晚上睡觉前玩会儿手机,但是应用的日间模式往往亮度太大,对眼睛有较为严重的伤害。因此,如今的应用往往开发了 日间和夜...
    99+
    2022-06-06
    Android
  • 单例模式在PHP中灵活运用的最佳实践
    在PHP编程中,设计模式是一种被广泛应用的技术,而单例模式是其中一种实用的设计模式。单例模式保证类在整个系统中只能被实例化一次,提供了全局访问的机制,适合在需要保持全局状态或共享资源的情况下使用。在本文中,我们将讨论如何在PHP中灵活地运用...
    99+
    2023-10-21
    PHP 单例模式 (Singleton) 最佳实践 (Best practice)
  • vue中使用Axios最佳实践方式
    目录1.前言2.使用2.1安装2.2基本用例2.2.1 get请求2.2.2post请求3.配置3.1语法3.2别名4.Axios实例4.1语法4.2请求配置4.3响应的配置配置的优...
    99+
    2022-11-13
  • MySQL中存储时间的最佳实践指南
    目录前言不要使用字符串存储时间类型MySQL 中的日期类型DATETIMETIMESTAMEPTIMESTAMP 的性能问题数值型时间戳(INT)DATETIME vs TIMEST...
    99+
    2022-11-12
  • Java建造者模式构建复杂对象的最佳实践
    目录介绍实现总结介绍 Java中的建造者模式是一种创建型设计模式,它的主要目的是为了通过一系列简单的步骤构建复杂的对象,允许创建复杂对象的不同表示形式,同时隐藏构造细节.它能够逐步构...
    99+
    2023-05-18
    Java建造者模式 Java设计模式
  • Kotlin Android中错误及异常处理最佳实践
    Kotlin Android中错误及异常处理最佳实践 Kotlin在Android开发中的错误处理机制以及其优势 Kotlin具有强大的错误处理功能:Kotlin提供了强大的错误处理功能,使处理错...
    99+
    2023-10-08
    android kotlin 开发语言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作