【android】夜间模式简单实现

关于阅读类的app,有个夜间模式真是太重要了。

那么有两种方式可以实现夜间模式

1:修改theme,重启activity

优点:正儿八经的夜间模式,配色看着舒服

缺点:图片刺眼、闪屏

2:使用一个带黑色带透明度的View,盖在现有的activity上,效果类似你带上墨镜,看着太阳不刺眼。

优点:不用重启activity,不闪屏;加上透明度过渡动画,模式之间切换非常舒服,解决了1中,白底图片依旧刺眼的问题。;

缺点:配色没变化,就算带上墨镜,白天依旧是白天。

因此,本方案整合了两种解决方案。在夜间配色的基础上,再加上一层墨镜,让图片也变得柔和起来,效果图如下:

可以看待chrome图标的白色底,在夜间模式下也变得柔和了

好,下面来讲讲具体的实现步骤,本环节使用的开发环境是android Studio

1 首先,在values下要准备好三个文件,没有就自己创建

attrs.xml(声明属性的类型,布局xml中用) reference可以使用系统的资源ID,比如R.color.gray; color可以直接使用#ffffff颜色代码

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="containerBackground" format="reference|color"></attr>
    <attr name="cardBackground" format="reference|color"></attr>
    <attr name="titleColor" format="reference|color"></attr>
    <attr name="textColor" format="reference|color"></attr>
    <attr name="selectorBtn" format="reference"></attr>
    <attr name="selectorListItem" format="reference"></attr>
</resources>

colors.xml(调色板,集中管理颜色hex)遵循优秀格式规范,即调色板模式,避免使用btn1,btn2,fontTitle,fontText之类的颜色名。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="white">#fafafa</color>
    <color name="white_dark">#f3f3f3</color>

    <color name="gray_light">#cccccc</color>
    <color name="gray">#777</color>
    <color name="gray_dark">#383838</color>

    <color name="green_light">#8e9ea4</color>
    <color name="green">#34515c</color>
    <color name="green_dark">#1e3e4a</color>

    <color name="night_mask">#90000000</color>
</resources>

styles.xml(日间、夜间主题)

<resources>
    <!-- Application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

    </style>
    <!-- 日间模式 -->
    <style name="AppTheme.day" parent="AppTheme">
        <item name="containerBackground">@color/white_dark</item>
        <item name="titleColor">@color/gray_dark</item>
        <item name="textColor">@color/gray</item>
        <item name="selectorBtn">@drawable/navigator_list_item_day</item>
        <item name="selectorListItem">@drawable/list_item_day</item>
    </style>
    <!-- 夜间模式 -->
    <style name="AppTheme.night" parent="AppTheme">
        <item name="containerBackground">@color/green_dark</item>
        <item name="titleColor">@color/white_dark</item>
        <item name="textColor">@color/green_light</item>
        <item name="selectorBtn">@drawable/navigator_list_item_night</item>
        <item name="selectorListItem">@drawable/list_item_night</item>
    </style>
</resources>

2定义activity父类,自动托管日间、夜间模式

BaseApplication就是自己包装的Application,通过它,保存日间、夜间模式

 Application和Activity,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息。通常我们是不需要指定一个Application的,这时系统会自动帮我们创建,如果需要创建自己 的Application,也很简单创建一个类继承 Application并在manifest的application标签中进行注册(只需要给Application标签增加个name属性把自己的 Application的名字定入即可)。

  android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局 的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些,数据传递,数据共享 等,数据缓存等操作。

public class BaseActionBarActivity extends ActionBarActivity {

    private BaseApplication mBaseApp = null;
    private WindowManager mWindowManager = null;
    private View mNightView = null;
    private LayoutParams mNightViewParam;
    private boolean mIsAddedView;   

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mBaseApp = (BaseApplication) getApplication();

        if (mBaseApp.isNightMode())
            setTheme(R.style.AppTheme_night);
        else
            setTheme(R.style.AppTheme_day);

        super.onCreate(savedInstanceState);

        mIsAddedView = false; 

        if (mBaseApp.isNightMode()) {
            initNightView();
            mNightView.setBackgroundResource(R.color.night_mask);
        }

    }

    @Override
    protected void onDestroy() {
        if (mIsAddedView) {
            mBaseApp = null;
            mWindowManager.removeViewImmediate(mNightView);
            mWindowManager = null;
            mNightView = null;
        }
        super.onDestroy();
    }

    public void ChangeToDay() {
        mBaseApp.setIsNightMode(false);
        mNightView.setBackgroundResource(android.R.color.transparent);
    }

    public void ChangeToNight() {
        mBaseApp.setIsNightMode(true);
        initNightView();
        mNightView.setBackgroundResource(R.color.night_mask);
    }

    /**
     * wait a time until the onresume finish
     */
    public void recreateOnResume() {
        new Handler().postDelayed(new Runnable() {
            public void run() {
                recreate();
            }
        }, 100);
    }

    private void initNightView() {
        if (mIsAddedView == true)
            return;
        mNightViewParam = new LayoutParams(
                LayoutParams.TYPE_APPLICATION,
                LayoutParams.FLAG_NOT_TOUCHABLE | LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSPARENT);

        mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        mNightView = new View(this);
        mWindowManager.addView(mNightView, mNightViewParam);
        mIsAddedView = true;
    }
}

值得一提的是recreateOnResume()函数,因为是从Resume里面重建activity的(避免闪屏)此时,直接调用系统的recreate函数时,会报错,原因是resume还没执行完,就被recreate了,因此,我们函数需要延时一会,等待系统完成resume就好了。一般延时1毫秒就可以了,但是我的app里面用到抽屉式导航栏,保存的时间要长点。

准备工作到这里已经结束了。只要activity集成自该父类,就会自动托管日间、夜间模式了

3调用方式

子类只要调用ChangeToDay、ChangeToNight就可以完成模式的切换了。别忘了recreate activity来生效哦,实例代码如下:

  void changeViewMode() {
        boolean isNight = getMyApplication().isNightMode();
        if (isNight)
            ChangeToDay();
        else
            ChangeToNight();

        recreate();
    }

OK,如过你能坚持看到这里,说明阁下是有耐心的人,奉上一个彩蛋。

关于WebView网页如何实现日间、夜间模式。

这个问题比我们现象的要简单的多。因为网页么,在生成html内容时,只要根据日间、还是夜间模式,替换css路径为日间.css、夜间.css就好了。

栗子来了,瞧,就是这个"{style}",我们要替换的对象。

<html>
<head>
    <title>Cnblogs</title>
    <link rel="stylesheet" type="text/css" href="{style}"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
    minimum-scale=1.0, user-scalable=no"/>
</head>

在对webview加载内容文本时,替换该字符串的css

replace("{style}",baseApplication.isNightMode() ? "style_night.css" : "style_day.css")

结构如下:

好了,大概思路,步骤代码都已经给出了,各位可以轻松给自己的app加上夜间模式

时间: 2024-10-29 19:11:24

【android】夜间模式简单实现的相关文章

Android夜间模式实现

查看我的全部开源项目[开源实验室] 欢迎加入我的QQ群:[201055521],本博客客户端下载[请点击] 本文原创,转载请注明地址:http://blog.kymjs.com/ 最近在做一个Android夜间模式的功能,又重新研究了一下Theme机制.贯彻我的风格,以解决问题为目标,写了个小Demo,简单了实现了切换夜间模式,为大家讲解. 在Activity中有一个方法叫setTheme(),可以设置Activity的Theme,当然Application类中也有相同的方法,也可以在Appli

Android 夜间模式的实现

package com.loaderman.daynightdemo; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatDelegate; import android.support.v7.widget.Toolbar; import android.view.View; public class MainActiv

Android 高级UI设计笔记24:Android 夜间模式之 WebView 实现白天 / 夜间阅读模式 (使用JavaScript)

1. 问题引入: 前面我们是使用方法 降低屏幕亮度(不常用) 和 替换theme,两者都是针对Activity的背景进行白天.夜间模式的交换,但是如果我们显示的是Html的内容,这个时候改怎么办? 分析:首先加载Html页面肯定是要用到WebView的,通过loadUrl的方法可以把html页面显示到webView,我们知道Android可以与JavaScript进行交互,就是说可以在JavaScript中调用Android的代码,也可以在Android中调用JavaScript代码. 所以就有

Android 高级UI设计笔记23:Android 夜间模式之 两种常用方法(降低屏幕亮度+替换theme)

1. 夜间模式 所谓的夜间模式,就是能够根据不同的设定,呈现不同风格的界面给用户,而且晚上看着不伤眼睛.特别是一些新闻类App实现夜间模式是非常人性化的,增强用户体验. 2. 我根据网上的资料 以及自己代码亲测,总结如下两种方法: (1)降低屏幕亮度 (2)替换theme 3. 夜间模式之 降低屏幕亮度: (1)创建一个Android工程,命名为"夜间模式_利用屏幕亮度(App)",如下: (2)首先我们来到主布局之中,如下: 1 <LinearLayout xmlns:andr

android MVP模式简单介绍

原文 http://zhengxiaopeng.com/2015/02/06/Android%E4%B8%AD%E7%9A%84MVP/ 前言 MVP作为一种MVC的演化版本在Android开发中受到了越来越多的关注,但在项目开发中选择一种这样的软件设计模式需保持慎重心态,一旦确定 使用MVP作为你App的开发模式那么你就最好坚持做下去,如果在使用MVP模式开发过程中发现问题而且坑越来越大,这时你想用MVC等来重新设计的话基 本上就等于推倒重来了.要知道在Android上MVP在现在为止并没有统

Android MVP模式简单介绍:以一个登陆流程为例

老的项目用的MVC的模式,最近完成了全部重构成MVP模式的工作,虽然比较麻烦,好处是代码逻辑更加清楚.简洁,流程更加清晰,对于后续版本迭代维护都挺方便.对于一些想要学习MVP模式的同学来讲,百度搜出来的好多都没法直接转化为项目里可以直接用的东西,所以这里正好拿出自己项目里已经用了的,你们可以直接用到自己的项目里.当然,不可能把所有项目代码在这里放出来,所以就拿登陆的流程出来,这个比较合适也比较常用. 1.先看下包结构: model:放一些bean类,以及网络处理类RetrofitManager,

android 建造者模式简单认识

1. 建造者模式的意思就是说将一个对象的各个部分一点一点进行建造(赋值),就像工地上盖房子,哪个部分要什么砖就单独的用一个方法设置这个砖块,不然的话就使用默认的砖块 2. 这里是一个Car的类,这个Car类包含了几个自身对应的属性,它的对象在创建的时候会有一些默认值.但是我们可以根据需要调用这个Car类的建造者类对象来对这个Car对象的具体属性赋值. 也就是说这里的Car的内部会有一个建造者类,这个类采用建造者模式来创建方法,他的方法会返回建造者对象,这样就能够不断的调用建造者对象中的赋值方法来

android简单的夜间模式

现在android项目values下打 attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <attr name="bookimage" format="reference|color" /> <attr name="tvcolor" format="reference|color&qu

Android 之夜间模式(多主题)的实现思路

实现思路 多数App由于历史原因当对其进行夜间模式的功能改造时,工作量是比较大的,所以在真正开始着手实现前,我们还是应该先明确夜间模式(多主题)到底有多少实现的思路以及它们的优劣,这样才可以有效的避免项目延期的情况出现. 自定义attr属性. 这是最基础的方法,就是通过自定义attr属性,在不同的theme中进行不同的实现,然后在layout和style中调用.这种方法改代码改动量比较大,而且根据不同的主题,drawable(5.0以上不用),selector等xml文件必须要相应的定义多份,因