怎么把App变成黑白色

3,139 阅读2分钟

4月4号是全国哀悼日,很多app都变成了黑白色,技术上是怎么实现的呢

很简单:在BaseActivity里添加如下代码:

@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    try{
        if ("FrameLayout".equals(name)) {
            int count = attrs.getAttributeCount();
            for (int i = 0; i < count; i++) {
                String attributeName = attrs.getAttributeName(i);
                String attributeValue = attrs.getAttributeValue(i);
                if (attributeName.equals("id")) {
                    int id = Integer.parseInt(attributeValue.substring(1));
                    String idVal = getResources().getResourceName(id);
                    if ("android:id/content".equals(idVal)) {
                        GrayFrameLayout grayFrameLayout = new GrayFrameLayout(context,attrs);
                        return grayFrameLayout;
                    }
                }
            }
        }
    }catch (Exception e) {

    }
    return super.onCreateView(name, context, attrs);
}

GrayFrameLayout是一个继承了FrameLaylayout的自定义类:代码如下:

public class GrayFrameLayout extends FrameLayout {
    private Paint mPaint = new Paint();

    public GrayFrameLayout(@NonNull Context context) {
        super(context);
    }

    public GrayFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);
        mPaint.setColorFilter(new ColorMatrixColorFilter(cm));
    }

    public GrayFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.saveLayer(null,mPaint,Canvas.ALL_SAVE_FLAG);
        super.draw(canvas);
        canvas.restore();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.saveLayer(null,mPaint,Canvas.ALL_SAVE_FLAG);
        super.dispatchDraw(canvas);
        canvas.restore();
    }
}    

这样就可以实现了,下面对代码分析一下,探索一下实现原理:

首先来看GrayFrameLayout

ColorMatrix是一个颜色矩阵,setSaturation是是设置饱和度,当值为0的时候,表示灰色,为1的时候表示原色,

mPaint.setColorFilter(new ColorMatrixColorFilter(cm));
表示把颜色矩阵设置的效果设置给画笔

再来看draw里面的方法,draw表示绘制自己

canvas.saveLayer(null,mPaint,Canvas.ALL_SAVE_FLAG);
表示创建一个新的Layer到栈中,当Layer入栈的时候,后续的draw操作都发生在这个Layer上
即:super.draw(canvas);表示在Layer上用饱和度为0(灰白色)的画笔绘制FrameLayout,
canvas.restore();表示Layer出栈,而Layer出栈时,就会把本层绘制的图像绘制到上层或者是Canvas上。

在来看dispatchDraw方法,其实它和draw方法很像,只不过它是分别以这种规则递归绘制子View,
这样GrayFrameLayout本身和它的子View都会被绘制成饱和度为0的黑白色了。

下面再来分析一下BaseActivity里面的onCreateView方法:

@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    try{
        if ("FrameLayout".equals(name)) {
            int count = attrs.getAttributeCount();
            for (int i = 0; i < count; i++) {
                String attributeName = attrs.getAttributeName(i);
                String attributeValue = attrs.getAttributeValue(i);
                if (attributeName.equals("id")) {
                    int id = Integer.parseInt(attributeValue.substring(1));
                    String idVal = getResources().getResourceName(id);
                    if ("android:id/content".equals(idVal)) {
                        GrayFrameLayout grayFrameLayout = new GrayFrameLayout(context,attrs);
                        return grayFrameLayout;
                    }
                }
            }
        }
    }catch (Exception e) {

    }
    return super.onCreateView(name, context, attrs);
}

这个方法就是用自定义的GrayFrameLayout替换Activity的默认的根View的FragmeLayout,这样,整个App都会变成灰色的了,实现原理就是这样的。

参考链接:juejin.cn/post/684490…