目前安卓有一个现成的卡片视图cardView,很方便可以直接导入。那么为什么要自制这个卡片视图呢?
答曰:androidx中的cardview美则美矣,但是它不能嵌入背景图片,只能使用app的卡片颜色设置背景颜色。另外当项目中不支持androidx(为什么?因为开发硬件平台没装,环境太低,导包很麻烦。)的时候,我发现想对容器边框动手还挺麻烦的!
那么,上干货。
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
/**
* <pre>
* author:yumei
* time:2023/08/23
* desc:自制圆角布局,没有伞的孩子要学会自己奔跑
* </pre>
*/
public class CardView extends FrameLayout {
private static final float cornerRadius=10f;
public CardView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void dispatchDraw(Canvas canvas) {
int height = getHeight();
int width = getWidth();
//如有需要,可改不同圆角
float topLeftRadius = cornerRadius;
float topRightRadius =cornerRadius;
float bottomRightRadius = cornerRadius;
float bottomLeftRadius = cornerRadius;
Path path = new Path();
path.moveTo(0, topLeftRadius);
path.arcTo(new RectF(0, 0, topLeftRadius * 2, topLeftRadius * 2), -180, 90);
path.lineTo(width - topRightRadius, 0);
path.arcTo(new RectF(width - 2 * topRightRadius, 0, width, topRightRadius * 2), -90, 90);
path.lineTo(width, height - bottomRightRadius);
path.arcTo(new RectF(width - 2 * bottomRightRadius, height - 2 * bottomRightRadius, width, height), 0, 90);
path.lineTo(bottomLeftRadius, height);
path.arcTo(new RectF(0, height - 2 * bottomLeftRadius, bottomLeftRadius * 2, height), 90, 90);
path.close();
canvas.clipPath(path);
super.dispatchDraw(canvas);
}
}
以上,在背景绘制的时候自定义一个path,然后让canvas沿着path裁剪。
这个方法的关键在于,先把canvas裁剪之后再调用父类同名方法。作者之前就一直在这里踩坑……原理就是在画背景的时候先把纸剪了,之后再怎么画也只是在纸上显示。
如果先调用父类同名方法再裁剪是没有用的,因为画前景的canvas是从父类传过去,不会搭理你重写的方法了。相当于把背景剪了,但是前景没剪,前景还是可以覆盖背景的图片。