Android自定义View绘制基础

大溪地,这就是你终生都在寻找的那座“爱情之岛”!

学习来源:HenCoder

总结

主要介绍使用 Paint 和 Canvas 绘制的常见API

  • paint 是画笔,能够添加画笔的颜色pain.setColor(int color)、画笔绘制的模式(实心paint.setStyle(Paint.Style.FILL),空心paint.setStyle(Paint.Style.STROKE))、画笔绘制的文本大小paint.setTextSize(int size),是否抗锯齿方式一:Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);方式二:paint.setAntiAlias(boolean open)(开启抗锯齿会使绘制的边缘更平滑),设置画笔的宽度paint.setStrokeWWidth(int width)
  • 使用 canvas 能够绘制线段(drawLine())、圆形(drawCircle())、画椭圆(drawOval())、扇形(drawArc())、矩形(drawRect())、画点(drawPoint())、文字(drawText())、图形drawPath()(图形包括所有能绘制的规则和不规则的内容)、Bitmap(drawBitmap())
绘制的关键
  • 自定义绘制的方式是重写绘制方法,其中最常用的是 onDraw()
  • 绘制的关键是 Canvas 的使用
    • Canvas 的绘制类方法: drawXXX() (关键参数:Paint)
  • 可以使用不同的绘制方法来控制遮盖关系(path.setFillType(FillType filltypr))
    • EVEN_ODD
    • WINDING (默认值)
    • INVERSE_EVEN_ODD
    • INVERSE_WINDING
从 onDraw( ) 开始表演吧

先来段代码看看如何开始自定义view

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Practice01View extends View {

Paint paint = new Paint();

public Practice01ClipRectView(Context context) {
super(context);
}

public Practice01ClipRectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

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

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制一个圆
canvas.drawCircle(300, 300, 200, paint);
}
}

步骤:

  • 创建一个类继承自View

  • 重写三个构造方法

  • 重写 onDraw() 方法

    • 可以看出在onDraw中用到了两个参数 canvas , paint
    • paint:相当于画笔的作用
    • canvas : 相当于画布的作用

Paint 常用的方法:

  • Paint.setStyle(Style style) 设置绘制模式
  • Paint.setColor(int color) 设置颜色
  • Paint.setStrokeWidth(float width) 设置线条宽度
  • Paint.setTextSize(float textSize) 设置文字大小
  • Paint.setAntiAlias(boolean aa) 设置抗锯齿开关

Canvas 常用的方法:

  • canvas.drawColor(int color):在整个绘制区域统一涂上参数所指定的颜色,主要用于绘制背景色
  • canvas.drawRGB(int r, int g, int b):效果同上
  • canvas.drawARGB(int a, int r, int g, int b):效果同上
  • canvas.drawCircle(float centerX, float centerY, float radius, Paint paint):画圆
  • canvas.drawRect(float left, float top, float right, float bottom, Paint paint):画矩形
  • canvas.drawPoint(float x, float y, Paint paint):画点,x,y是点的坐标
  • canvas.drawPoints(float[] pts, int offset, int count, Paint paint) / drawPoints(float[] pts, Paint paint):批量画点
  • canvas.drawOval(float left, float top, float right, float bottom, Paint paint):画椭圆
  • canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint):画线
  • drawLines(float[] pts, int offset, int count, Paint paint) / drawLines(float[] pts, Paint paint) 画线(批量)
  • canvas.drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint):画圆角矩形
  • canvas.drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean userCenter, Paint paint):画扇形或者弧形
  • canvas.drawPath(Path path, Paint paint):画自定义的图形,Path 可以描述直线、二次曲线、三次曲线、圆、椭圆、弧形、矩形、圆角矩形。把这些图形结合起来,就可以描述出很多复杂的图形

Path 有两类方法,一类是直接描述路径的,另一类是辅助的设置或计算

Path 方法第一类:直接描述路径,添加子图形和画线(直线或曲线)
第一组: addXxx() ——添加子图形
  • addCircle(float x, float y, float radius, Direction dir) 添加圆
    最后一个参数 dir 是画圆的路径的方向。
    路径方向有两种:顺时针 (CW clockwise) 和逆时针 (CCW counter-clockwise) 。对于普通情况,这个参数填 CW 还是填 CCW 没有影响。它只是在需要填充图形 (Paint.Style 为 FILL 或 FILL_AND_STROKE) ,并且图形出现自相交时,用于判断填充范围的。
  • addOval(float left, float top, float right, float bottom, Direction dir) 添加椭圆
  • addOval(RectF oval, Direction dir) 添加椭圆
  • addRect(float left, float top, float right, float bottom, Direction dir) 添加矩形
  • addRect(RectF rect, Direction dir) 添加矩形
  • addRoundRect(RectF rect, float rx, float ry, Direction dir) 添加圆角矩形
  • addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Direction dir) 添加圆角矩形
  • addRoundRect(RectF rect, float[] radii, Direction dir) 添加圆角矩形
  • addRoundRect(float left, float top, float right, float bottom, float[] radii, Direction dir) 添加圆角矩形
  • addPath(Path path) 添加另一个 Path
第二组:xxxTo() ——画线(直线或曲线)
  • lineTo(float x, float y)
  • rLineTo(float x, float y) 画直线
    这两个方法的区别是,lineTo(x, y) 的参数是绝对坐标,而 rLineTo(x, y) 的参数是相对当前位置(最后一次绘制的坐标画 Path 的方法的终点位置。初始值为原点 (0, 0))的相对坐标
  • quadTo(float x1, float y1, float x2, float y2)
  • rQuadTo(float dx1, float dy1, float dx2, float dy2) 画二次贝塞尔曲线
    贝塞尔曲线是几何上的一种曲线。它通过起点、控制点和终点来描述一条曲线,主要用于计算机图形学
  • cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
  • rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) 画三次贝塞尔曲线(原理同上)
  • moveTo(float x, float y) / rMoveTo(float x, float y) 移动到目标位置
    不论是直线还是贝塞尔曲线,都是以当前位置作为起点,而不能指定起点。但你可以通过 moveTo(x, y) 或 rMoveTo() 来改变当前位置,从而间接地设置这些方法的起点
  • arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
  • arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(RectF oval, float startAngle, float sweepAngle) 画弧形
    这个方法和 Canvas.drawArc() 比起来,少了一个参数 useCenter,而多了一个参数 forceMoveTo 。
    少了 useCenter ,是因为 arcTo() 只用来画弧形而不画扇形,所以不再需要 useCenter 参数;而多出来的这个 forceMoveTo 参数的意思是,绘制是要「抬一下笔移动过去」,还是「直接拖着笔过去」,区别在于是否留下移动的痕迹。
  • addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)
  • addArc(RectF oval, float startAngle, float sweepAngle)
    又是一个弧形的方法。一个叫 arcTo ,一个叫 addArc(),都是弧形,区别在哪里?其实很简单: addArc() 只是一个直接使用了 forceMoveTo = true 的简化版 arcTo() 。
  • close() 封闭当前子图形
Path 方法第二类:辅助的设置或计算

Canvas 还可以绘制 Bitmap

  • drawBitmap(Bitmap bitmap, float left, float top, Paint paint) 画 Bitmap
  • drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
  • drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
  • drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
  • drawBitmapMesh(),可以绘制具有网格拉伸效果的 Bitmap

Canvas 还可以绘制文字

  • drawText(String text, float x, float y, Paint paint) 绘制文字
小额支持我写出更好的文章~