【Android】仿知乎夜间模式的实现

1.简介

目前很多App都有夜间模式的功能,网上教程也是很多,最近项目不忙,抽空学习了下,在这做下记录,希望能帮到正在看博客的你,我们先来看下知乎的效果:

【Android】仿知乎夜间模式的实现_第1张图片

看我的效果:

卧槽,好像啊,哈哈,好吧,有点神似,关于知乎实现的分析,大家可以看下这位大神的分析,那咱们废话少说,开始实现吧。

2.AppCompatDelegate方式实现

在support.v7包中google提供了AppCompatDelegate类,可以用于实现夜间模式,实现起来比较简单:

一、设置Activity主题,继承自Theme.AppCompat.DayNight等夜间相关的主题

<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">

二、通过setDefaultNightMode(Mode)方法来设置当前的模式

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

该模式有三种

  • AppCompatDelegate.MODE_NIGHT_AUTO,他会时刻知道你最后的位置和时间(如果您的应用程序已开启位置权限)用于白天和黑夜之间自动切换的 依据
  • AppCompatDelegate.MODE_NIGHT_NO 强制设定了从不使用夜晚主题。
  • AppCompatDelegate.MODE_NIGHT_YES 则强制设定了一直使用夜晚主题。

以上来自模式介绍.

三、通过在res目录下建立value-night,drawable-night等目录来进行匹配,当设置为夜间模式的时候,会取-night下的资源,反之,会取默认的资源,看下效果:

【Android】仿知乎夜间模式的实现_第2张图片

以上实现的是白天和夜间分别加载不同的图片和background,不过使用这种方式有个问题,就是如果设置夜间模式后,不进行跳转,本页面要想有反应必须调用activity的recreate()方法,会出现闪屏问题,所以虽然实现简单,但是效果并不好,这里不再过多介绍,源码下载文末给出。

3.仿知乎夜间模式的实现

思路借鉴上文对知乎分析文章的介绍,首先制造出一个和当前页面一样的ImageView放在页面的最上层,然后切换夜间模式时,设置需要设置的颜色,背景等属性,然后对ImageView进行颜色渐变的实现,使其看起来更平滑,说的有点乱,看具体步骤:

一、获取布局文件最外层Layout的截图

/**
     * 获取view截图对应的bitmap
     * @param v
     * @return
     */
    public Bitmap loadBitmapFromView(View v) {
        //width为屏幕宽度,height为屏幕高度,statusBarHeight为状态栏高度
        Bitmap b = Bitmap.createBitmap(width, height-statusBarHeight, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(b);
        v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
        v.draw(c);
        return b;
    }

二、创建临时的ImageView并add到rootLayout中

final ImageView imageView = new ImageView(this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(width, height-statusBarHeight));
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
Bitmap bitmap = loadBitmapFromView(rootLayout);
imageView.setImageBitmap(bitmap);
rootLayout.addView(imageView);

四、设置夜间/日间模式

/**
     * 设置日渐模式具体代码
     */
    private void setDayThemeInfo() {
        rootLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));
        tvColor.setTextColor(Color.parseColor("#222222"));
        imageView.setImageResource(R.mipmap.day_icom);
    }

/**
     * 设置夜间模式具体代码
     */
    private void setNightThemeInfo() {
        rootLayout.setBackgroundColor(Color.parseColor("#333444"));
        tvColor.setTextColor(Color.parseColor("#666666"));
        imageView.setImageResource(R.mipmap.night_icon);
    }

五、渐变动画,移除临时的ImageView

        int colorA = Color.parseColor("#ffffff");
        int colorB = Color.parseColor("#333444");
        ObjectAnimator objectAnimator = ObjectAnimator.ofInt(imageView, "backgroundColor", colorA, colorB);
        objectAnimator.setDuration(800);
        objectAnimator.setEvaluator(new ArgbEvaluator());
        objectAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                rootLayout.removeView(imageView);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        objectAnimator.start();

在以上介绍中,省略了一些简单的步骤,比如获取屏幕宽高,布局文件也没有贴出来,实际项目中肯定还需要保存当前的模式,一般使用SharedPreferences保存即可,然后初始化的时候加载相应的设置主题的代码,不再敖述。

【Android】仿知乎夜间模式的实现_第3张图片

本文旨在给出一些基本的思路和简单实现,具体使用中还需对细节进行处理,望各位看官注意!

【Android】仿知乎夜间模式的实现_第4张图片



源码在这里:夜间模式源码点击下载

你可能感兴趣的:(android开发进阶)