为什么需要自定义View
Android提供了一些原生的控件如TextView、ImageView、RelativeLayout等,但是这些原生控件有时候不能满足我们的产品设计需求,这时候就要用到自定义控件。
怎样实现自定义View
这段文字翻译自Android官方文档:要实现自定义View,您通常首先要重写一些框架调用所有View的标准方法。您不需要覆盖所有这些方法。实际上,您可以从重写onDraw(android.graphics.Canvas)开始。附图(图片来自Android官方文档)。
步骤
- 创建类继承原生控件
- 重写相应的标准方法
例子
经常遇到这样的需求,ImageView要显示圆角图片。原生的ImageView不能满足我们的需求,这时候就需要自定义View了。
- 创建RoundRectImageView继承ImageView
- 重写onSizeChanged
- 重写onDraw
public class RoundRectImageView extends ImageView {
private Path path;//路径,用来选取绘画区域
private RectF rectF;//矩形,确定路径时用到
private float[] cornerRadius;//存放四个角的圆角半径,确定路径时用到
private Paint paint;//画笔,反锯齿
private int cornerColor;//角的颜色,设置角的颜色跟背景色一样形成圆角效果
public RoundRectImageView(Context context) {
this(context, null);
}
public RoundRectImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundRectImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//初始化
path = new Path();
rectF = new RectF();
rectF.left = 0;
rectF.top = 0;
cornerRadius = new float[8];
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
cornerColor = Color.WHITE;
}
//重置路径
private void resetPath() {
path.rewind();
path.addRoundRect(rectF, cornerRadius, Path.Direction.CW);
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);//设置成反奇偶规则
}
@Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
rectF.right = w;
rectF.bottom = h;
resetPath();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(cornerColor);
canvas.drawPath(path, paint);
}
/*
* @param leftTopRadius 左上角的圆角半径
* @param rightTopRadius 右上角的圆角半径
* @param leftBottomRadius 左下角的圆角半径
* @param rightBottomRadius 右下角的圆角半径
*/
public void setCornerRadius(int leftTopRadius, int rightTopRadius, int leftBottomRadius, int rightBottomRadius) {
cornerRadius[0] = leftTopRadius;
cornerRadius[1] = leftTopRadius;
cornerRadius[2] = rightTopRadius;
cornerRadius[3] = rightTopRadius;
cornerRadius[4] = rightBottomRadius;
cornerRadius[5] = rightBottomRadius;
cornerRadius[6] = leftBottomRadius;
cornerRadius[7] = leftBottomRadius;
resetPath();
invalidate();
}
//设置圆角颜色
public void setCornerColor(int cornerColor) {
this.cornerColor = cornerColor;
invalidate();
}
}
通过setRadius(int, int, int, int)方法设置图片的四个圆角、setCornerColor(int)设置圆角的颜色,其它用法跟ImageView一样。
path.setFillType(Path.FillType.INVERSE_EVEN_ODD)解释:当我们要给一个封闭的路径内部填充颜色时,首先需要分清哪一部分是外部,哪一部分是内部。Path类有一个方法setFillType(FillType ft) :设置路径的填充类型,这定义了如何计算“内部”。我们设置成反奇偶规则的效果是:从任意位置(绘制区域内)o作一条射线, 若与该射线相交的路径边的数目为奇数,则o是路径外部,否则就是路径内部如i1、i2。附图。
原图:
效果图1:roundRectImageView.setRadius(50, 50, 50, 50);
效果图2:roundRectImageView.setRadius(50, 50, 50, 0);