如何实现特殊日期界面灰色模式?

Quibbler 2022-11-30 526

如何实现特殊日期界面灰色模式?


        在特殊的日期为了缅怀和纪念,比如清明节等,淘宝、京东、拼多多等应用的首页自动切换成灰白主题的样式。


        先看看如何快速实现这个功能,服务端可以将图片灰度预处理,前端也能将界面呈现灰度。按照置灰作用区域分:局部View、单个Activity页面、整个应用。

        局部View置灰:淘宝APP使用局部View灰色的方法,首页往下滑动出来的不再呈现灰白色。

        单个Activity置灰:优酷、知乎等APP使用单个Activity页面呈现灰色的方法。

        整个应用置灰:工商银行APP使用这种全局灰色的方法。


        首先,要了解View中的setLayerType(int layerType,Paint paint)方法,借助该方法,创建一个新的透明图层,在新的图层上绘制,有类似“遮罩”的效果。

    public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
        }
        boolean typeChanged = mRenderNode.setLayerType(layerType);
        if (!typeChanged) {
            setLayerPaint(paint);
            return;
        }
        if (layerType != LAYER_TYPE_SOFTWARE) {
            // Destroy any previous software drawing cache if present
            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
            // drawing cache created in View#draw when drawing to a SW canvas.
            destroyDrawingCache();
        }
        mLayerType = layerType;
        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
        mRenderNode.setLayerPaint(mLayerPaint);
        // draw() behaves differently if we are on a layer, so we need to
        // invalidate() here
        invalidateParentCaches();
        invalidate(true);
    }

        其次,需要用到ColorMatrix颜色矩阵,常用于颜色的转换、图片处理。该类中有一个setSaturation(float sat)方法。当参数为 0 时转换为灰色,为 1 时恢复为原本的颜色。

    /**
     * Set the matrix to affect the saturation of colors.
     *
     * @param sat A value of 0 maps the color to gray-scale. 1 is identity.
     */
    public void setSaturation(float sat) {
        reset();
        float[] m = mArray;
        final float invSat = 1 - sat;
        final float R = 0.213f * invSat;
        final float G = 0.715f * invSat;
        final float B = 0.072f * invSat;
        m[0] = R + sat; m[1] = G;       m[2] = B;
        m[5] = R;       m[6] = G + sat; m[7] = B;
        m[10] = R;      m[11] = G;      m[12] = B + sat;
    }


1、局部View置灰

        借助ViewColorMatrix,可以很方便的使View呈现灰白效果。使用Kotlin,写成View的扩展方法,以方便调用。

    fun View.grayMode() {
        val colorMatrix = ColorMatrix().apply {
            setSaturation(0f)
        }
        val paint = Paint().apply {
            colorFilter = ColorMatrixColorFilter(colorMatrix)
        }
        setLayerType(View.LAYER_TYPE_HARDWARE, paint)
    }


2、单个Activity置灰

        除了让特定View/ViewGroup范围内的区域呈现灰白效果,还可以对Activity进行操作,让整个Activity页面变成灰白色。只需要利用Window中的DecorView,参考《Activity的组成结构》一文。

        扩展方法如下:

    fun Activity.grayMode() {
        val colorMatrix = ColorMatrix().apply {
            setSaturation(0f)
        }
        val paint = Paint().apply {
            colorFilter = ColorMatrixColorFilter(colorMatrix)
        }
        window?.decorView?.setLayerType(View.LAYER_TYPE_HARDWARE, paint)
    }


3、整个应用置灰

        最后,还有全局页面的Hook。只需在Application里通过registerActivityLifecycleCallbacks()方法注册ActivityLifecycleCallbacks监听Activity的生命周期,参考《Activity生命周期监听ActivityLifecycleCallbacks》一文。使整个应用所有的Activity页面都能实现灰白效果:

    override fun onCreate() {
        super.onCreate()
        
        //注册ActivityLifecycleCallbacks
        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks{
            
            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
                activity.grayMode()
            }
            ...
        })
        
    }

        市面上的应用基本上都只是首页特殊处理,其它页面还是正常显示,降低对使用体验的影响。


        最后结合相关业务,在启动时通过服务端去更新客户端的配置,再根据此条件(比如日期)触发即可。     

    //Whether it is a mourning day or not, should a gray interface be displayed
    if (!mourningDay()) return
    ...

        不知道有没有人能注意到,“灰白模式”其实和开发者选项中的模拟颜色空间 > 全色盲调试选项效果类似。


        

不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com