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都会变成灰色的了,实现原理就是这样的。