关于夜间模式的总结

 

关于夜间模式的总结

1.目前自己做的案例

  • 1. 那么有两种方式可以实现夜间模式
    • 1:修改theme,重启Activity
      • 优点:正儿八经的夜间模式,配色看着舒服
      • 缺点:图片刺眼、闪屏
    • 2:使用一个带黑色带透明度的View,盖在现有的activity上【遮罩层】
      • 优点:不用重启activity,不闪屏;加上透明度过渡动画,模式之间切换非常舒服,解决了1中,白底图片依旧刺眼的问题。;
      • 缺点:配色没变化,就算带上墨镜,白天依旧是白天。
  • 2.使用步骤
    • 1.首先,在values下要准备好三个文件,没有就自己创建

 

175144_tsMs_3027457.png

 

      • 说明: 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 name="titleColor" format="reference|color"/>

    <attr name="textColor" format="reference|color"/>

    <attr name="selectorBtn" format="reference"/>

    <attr name="selectorListItem" format="reference"/>

    <attr name="personCenterTextColor" format="reference|color"/>

    <attr name="intervalBg" format="reference|color"/>

    <attr name="underLine" format="reference|color"/>

    <attr name="grayTextColor" format="reference|color"/>

</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父类和Application,自动托管日间、夜间模式
      • 说明:BaseApplication就是自己包装的Application,通过它,保存日间、夜间模式
      • Application和Activity一样是android框架的一个系统组件,当android程序启动时系统会创建一个application对象,用来存储系统的一些信息。
      • android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局 的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些,数据传递,数据共享等,数据缓存等操作。
      • 在自定义Application中
@Override

public void onCreate() {

    super.onCreate();

    ……

    //记录夜间模式状态。这个SP值很重要,不要随便清理SP中的值

    mSp = PreferenceManager.getDefaultSharedPreferences(this);

    mIsNightMode = mSp.getBoolean(PARAM_IS_NIGHT_MODE, false);

}


private boolean mIsNightMode;

private SharedPreferences mSp;

private static final String PARAM_IS_NIGHT_MODE = "PARAM_IS_NIGHT_MODE";

public boolean isNightMode() {

    return mIsNightMode;

}


public void setIsNightMode(boolean isNightMode) {

    if (mIsNightMode == isNightMode)

        return;

    mIsNightMode = isNightMode;

    mSp.edit().putBoolean(PARAM_IS_NIGHT_MODE, mIsNightMode).apply();

}
      • 在BaseActivity中
@Override

protected void onCreate(Bundle savedInstanceState) {

    mBaseApp = (BaseApplication) getApplication();

    if (mBaseApp.isNightMode()){

        setTheme(isSwipeToClose() ? R.style.AppTheme_night_transparent : R.style.AppTheme_night);

    } else{

        setTheme(isSwipeToClose() ? R.style.AppTheme_day_transparent : 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();

}


protected void initNightView() {

    if (mIsAddedView)

        return;

    WindowManager.LayoutParams mNightViewParam = new WindowManager.LayoutParams(

            WindowManager.LayoutParams.TYPE_APPLICATION,

            WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,

            PixelFormat.TRANSPARENT);


    mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

    mNightView = new View(this);

    mWindowManager.addView(mNightView, mNightViewParam);

    mIsAddedView = true;

}


protected void ChangeToDay() {

    mBaseApp.setIsNightMode(false);

    mNightView.setBackgroundResource(android.R.color.transparent);

}


protected void ChangeToNight() {

    mBaseApp.setIsNightMode(true);

    initNightView();

}

调用方式

isNight = BaseApplication.getInstance().isNightMode();

if (isNight) {

    ChangeToDay();

} else {

    ChangeToNight();

}

recreate();

    • 3.如何在布局中引用资源

  • 3.关于WebView网页如何实现日间、夜间模式
    • 先了解js的切换夜间模式的点击事件接口

    • 在代码里写【关键代码】
ws = webView.getSettings();

ws.setJavaScriptEnabled(true);

webView.setWebViewClient(new MyWebViewClient());


private class MyWebViewClient extends WebViewClient {

    @Override

    public void onPageFinished(WebView view, String url) {

        view.getSettings().setJavaScriptEnabled(true);

        super.onPageFinished(view, url);

        if (isNight) {

            webView.loadUrl("javascript:toggleClassTest()");

        }

    }

}

 

2.简单优雅使用Android7.0实现夜间模式

  • 1.关于Android7.0夜间模式新特性
    • 事实上,日间模式与夜间模式就是给APP定义并应用两套不同颜色的主题。用户可以自动或者手动的开启。
    • Android 6.0 Marshmallow 预览版中曾经短暂出现过相关的夜间模式的功能,只是在正式版中被移除了,在Android 7.0 Nougat上,用户们再次经历了「得而复失」的遗憾,在开发者预览版中,夜间模式和暗色模式先是开启,然后有再次被移除。而在正式版中,夜间模式也没有出现。但其实相关的代码一直存在于系统中,只是默认没有被开启。
  • 2.实现步骤
    • 1.添加依赖库

compile 'com.android.support:appcompat-v7:25.1.1'

compile 'com.android.support:design:25.1.1'

由于Support Library在23.2.0的版本中才添加了Theme.AppCompat.DayNight主题,所以依赖的版本必须是高于23.2.0的,并且,这个特性支持的最低SDK版本为14,所以,需要兼容Android 4.0的设备,是不能使用这个特性的,在API Level 14以下的设备会默认使用亮色主题。不过现在4.0以下的设备应该比较少了吧,毕竟微信的minSdkVersion都设置为14了。

    • 2.准备资源
      • 1.让我们自己的主题继承并应用DayNight主题。
<style name="AppTheme" parent="Theme.AppCompat.DayNight.DarkActionBar">

        <item name="colorPrimary">@color/colorPrimary</item>

        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>

        <item name="colorAccent">@color/colorAccent</item>

        <!--customize your theme here 下面可以自定义-->

</style>
      • 2.新建资源文件

 

新建夜间模式资源文件夹:在res目录下新建values-night文件夹,然后在此目录下新建colors.xml文件在夜间模式下的应用的资源。当然也可以根据需要新建drawable-night,layout-night等后缀为-night的夜间资源文件夹。

 

在value中的color文件

<!--values-colors.xml-->

<resources>

    <color name="colorPrimary">#009688</color>

    <color name="colorPrimaryDark">#00796B</color>

    <color name="colorAccent">#009688</color>

    <color name="textColorPrimary">#616161</color>

    <color name="viewBackground">@android:color/white</color>

</resources>

在value-night的color文件

<!--values-night-colors.xml-->

<resources>

    <color name="colorPrimary">#35464e</color>

    <color name="colorPrimaryDark">#212a2f</color>

    <color name="colorAccent">#212a2f</color>

    <color name="textColorPrimary">#616161</color>

    <color name="viewBackground">#212a2f</color>

</resources>
      • 3. 使Activity继承自AppCompatActivity
    • 3.在自定义Application中
public class App extends Application {

    @Override

    public void onCreate() {

        super.onCreate();

        // the 'theme' has two values, 0 and 1

        // 0 --> day theme, 1 --> night theme

        if (getSharedPreferences("user_settings",MODE_PRIVATE).getInt("theme", 0) == 0) {

            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);

        } else {

            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

        }

    }

}

 

注意:

                 这里AppCompatDelegate.setDefaultNightMode()方法可以接受的参数值有4个:

        • MODE_NIGHT_NO. (一直应用日间(light)主题).
        • MODE_NIGHT_YES. (一直使用夜间(dark)主题).
        • MODE_NIGHT_AUTO. (根据当前时间在day/night主题间切换).
        • MODE_NIGHT_FOLLOW_SYSTEM(默认选项)(跟随系统,通常为MODE_NIGHT_NO).
    • 4.动态调用切换夜间模式
SharedPreferences sp =  getSharedPreferences("user_settings",MODE_PRIVATE);

if ((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES) {

    sp.edit().putInt("theme", 0).apply();

    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);

} else {

    sp.edit().putInt("theme", 1).apply();

    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

}

//过渡动画效果,防止切换夜间模式闪屏
 

getWindow().setWindowAnimations(R.style.WindowAnimationFadeInOut);

recreate();

 

注意:

在调用recreate()方法之前,还可以创建一些动画进行过渡。

过渡动画

<style name="WindowAnimationFadeInOut">

    <item name="android:windowEnterAnimation">@anim/fade_in</item>

    <item name="android:windowExitAnimation">@anim/fade_out</item>

</style>

fade_in.xml动画文件

<set xmlns:android="http://schemas.android.com/apk/res/android">

    <alpha

        android:duration="1000"

        android:fromAlpha="0"

        android:interpolator="@android:anim/decelerate_interpolator"

        android:toAlpha="1.0" />

</set>
    • 5.设置自定义属性,比如文字,按钮,容器背景等颜色
android:textColor="@color/textColor"

这样就可以根据属性切换字体颜色

values中color     

<color name="textColor">#FF0000</color>

night-values中color

<color name="textColor">#039BE5</color>
    • 6.注意事项

在Android 6.0及以下的设备上,本项目运行时会有切换的过渡动画效果,但是不支持Android 7.0及以上的设备

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/zbj1618/blog/847954

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值