在自定义控件特别是自绘控件的时候,都会去重写onDraw方法,就会涉及到Paint和Canvas的使用,前面两篇播客说了下Paint的基本使用,这里说下Canvas的基本使用。Canvas:画布,通俗的说就是一个载体,比如在纸上写字,那么Canvas就类似于纸,Canvas可以绘制直线、点、几何图形、曲线、Bitmap、圆弧等等。
Canvas绘制直线
//startX X的起点 startY Y的起点 stopX X的终点 stopY Y的终点 //paint画笔
canvas.drawLine(float startX, float startY, float stopX, float stopY,@NonNull Paint paint);
下面这两个api是绘制一系列直线:
/**
*
* @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
* @param offset Number of values in the array to skip before drawing.
* @param count The number of values in the array to process, after
* skipping "offset" of them. Since each line uses 4 values,
* the number of "lines" that are drawn is really
* (count >> 2).
* @param paint The paint used to draw the points
*/
public void drawLines(@Size(multiple=4) @NonNull float[] pts, int offset, int count,
@NonNull Paint paint) {
}
public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint) {
}
进行绘制:
mPaint.setColor(Color.GRAY);
//绘制线条
canvas.drawLine(50, 0, 500, 500, mPaint);
mPaint.setColor(Color.RED);
//绘制一系列线条
float []pts = {50,50,100,100,200,200,300,300,400,400,500,500};
canvas.drawLines(pts,mPaint);
// canvas.drawLines(pts, 10, 2, mPaint);//通过offset设置线的间隔距离,可以实现虚线效果
效果:
Canvas绘制点:
canvas.drawPoint(float x, float y, @NonNull Paint paint);
绘制一系列的点:
/**
*
* @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
* @param offset Number of values to skip before starting to draw.
* @param count The number of values to process, after skipping offset
* of them. Since one point uses two values, the number of
* "points" that are drawn is really (count >> 1).
* @param paint The paint used to draw the points
*/
public void drawPoints(@Size(multiple=2) float[] pts, int offset, int count,
@NonNull Paint paint) {
}
/**
* Helper for drawPoints() that assumes you want to draw the entire array
*/
public void drawPoints(@Size(multiple=2) @NonNull float[] pts, @NonNull Paint paint) {
}
使用:
mPaint.setColor(Color.GRAY);
//绘制一个点
canvas.drawPoint(30,30, mPaint);
mPaint.setColor(Color.RED);
//绘制一系列点
float []pts = {50,50,100,100,200,200,300,300,400,400,500,500};
canvas.drawPoints(pts,mPaint);
效果:
Canvas绘制矩形:
/**
* @param rect The rect to be drawn RectF构造方法的四个参数是float类型
* @param paint The paint used to draw the rect
*/
public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
}
/**
* @param r The rectangle to be drawn. Rect构造方法的四个参数为int型
* @param paint The paint used to draw the rectangle
*/
public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
}
/**
* @param left The left side of the rectangle to be drawn
* @param top The top side of the rectangle to be drawn
* @param right The right side of the rectangle to be drawn
* @param bottom The bottom side of the rectangle to be drawn
* @param paint The paint used to draw the rect
*/
public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
}
使用:
//方式一
mPaint.setColor(Color.GRAY);
canvas.drawRect(50, 50, 100, 200,mPaint);
//方式二
mPaint.setColor(Color.RED);
RectF rectf=new RectF(160f, 50f, 210f, 200f);
canvas.drawRect(rectf,mPaint);
//方式三
Rect rect=new Rect(260,50,310,200);
canvas.drawRect(rect,mPaint);
效果:
Canvas绘制圆角矩形:
/**
* @param rect The rectangular bounds of the roundRect to be drawn
* @param rx The x-radius of the oval used to round the corners
* @param ry The y-radius of the oval used to round the corners
* @param paint The paint used to draw the roundRect
*/
public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
}
/**
*api>=21才可以使用
* @param rx The x-radius of the oval used to round the corners
* @param ry The y-radius of the oval used to round the corners
* @param paint The paint used to draw the roundRect
*/
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
@NonNull Paint paint) {
}
使用:
mPaint.setColor(Color.GRAY);
//api2>=21 才可以使用
//canvas.drawRoundRect(50, 50, 100, 200,10,10,mPaint);
mPaint.setColor(Color.RED);
RectF rectf=new RectF(160f, 50f, 210f, 200f);
canvas.drawRoundRect(rectf,10,10,mPaint);
效果:
Canvas绘制圆:
/**
* @param cx The x-coordinate of the center of the cirle to be drawn
* @param cy The y-coordinate of the center of the cirle to be drawn
* @param radius The radius of the cirle to be drawn
* @param paint The paint used to draw the circle
*/
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
}
使用:
mPaint.setColor(Color.RED);
canvas.drawCircle(200,200,100,mPaint);
效果:
Canvas绘制椭圆:
/**
*
* @param oval The rectangle bounds of the oval to be drawn
*/
public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
if (oval == null) {
throw new NullPointerException();
}
drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
}
/**
*api>=21才可以使用
* Draw the specified oval using the specified paint. The oval will be
* filled or framed based on the Style in the paint.
*/
public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
native_drawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
}
使用:
//api2>=21 才可以使用
// canvas.drawOval(50, 50, 100, 200,mPaint);
RectF rectf=new RectF(50, 50, 100, 200);
canvas.drawOval(rectf,mPaint);
效果:
Canvas绘制弧:
/**
* @param oval The bounds of oval used to define the shape and size
* of the arc
* @param startAngle Starting angle (in degrees) where the arc begins
* @param sweepAngle Sweep angle (in degrees) measured clockwise
* @param useCenter If true, include the center of the oval in the arc, and
close it if it is being stroked. This will draw a wedge
false:只有一个纯弧线;true:闭合的边
* @param paint The paint used to draw the arc
*/
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint) {
drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
paint);
}
/**
*
* @param startAngle Starting angle (in degrees) where the arc begins 其实角度,相对X轴正方向
* @param sweepAngle Sweep angle (in degrees) measured clockwise 画多少角度的弧度
* @param useCenter If true, include the center of the oval in the arc, and
close it if it is being stroked. This will draw a wedge
false:只有一个纯弧线;true:闭合的边
* @param paint The paint used to draw the arc
*api2>=21 才可以使用
*/
public void drawArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean useCenter, @NonNull Paint paint) {
native_drawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
useCenter, paint.getNativeInstance());
}
使用:
//api2>=21 才可以使用
// canvas.drawArc(50, 50, 100, 200,0,270,false,mPaint);
RectF rectf=new RectF(100, 100, 400, 500);
canvas.drawArc(rectf,0,90,false,mPaint);
效果:
另外Canvas还可以drawBitmap、drawText、drawPath等方法可以调用;
Canvas变换技巧
使用Canvas的变换技巧可以实现平移、缩放、旋转,斜拉、裁剪等效果
1.1、平移
/**
* Preconcat the current matrix with the specified translation
*
* @param dx The distance to translate in X
* @param dy The distance to translate in Y
*/
public void translate(float dx, float dy) {
native_translate(mNativeCanvasWrapper, dx, dy);
}
使用:
RectF rectf=new RectF(0, 0, 400, 500);
canvas.drawRect(rectf,mPaint);
//将画布平移
mPaint.setColor(Color.YELLOW);
canvas.translate(50,50);
//平移后重新绘制矩形
canvas.drawRect(rectf,mPaint);
注意:平移后绘制矩形的时候就是一个新的画布,当canvas执行drawXXX的时候就会新建一个新的画布图层
效果:
1.2、缩放
/**
* Preconcat the current matrix with the specified scale.
*
* @param sx The amount to scale in X
* @param sy The amount to scale in Y
* sx,sy:分别对x/y方向的一个缩放系数,画布的缩放会导致里面所有的绘制的东西都会有一个缩放效果
*/
public void scale(float sx, float sy) {
native_scale(mNativeCanvasWrapper, sx, sy);
}
/**
* Preconcat the current matrix with the specified scale.
*
* @param sx The amount to scale in X
* @param sy The amount to scale in Y
* @param px The x-coord for the pivot point (unchanged by the scale)
* @param py The y-coord for the pivot point (unchanged by the scale)
*/
public final void scale(float sx, float sy, float px, float py) {
translate(px, py);
scale(sx, sy);
translate(-px, -py);
}
使用:
RectF rectf=new RectF(0, 0, 400, 500);
canvas.drawRect(rectf,mPaint);
//将画布缩放
mPaint.setColor(Color.YELLOW);
canvas.scale(1.5f,0.5f);
//缩放后重新绘制矩形
canvas.drawRect(rectf,mPaint);
效果:
1.3、旋转
/**
* Preconcat the current matrix with the specified rotation.
*
* @param degrees The amount to rotate, in degrees
*默认px和py为0
*/
public void rotate(float degrees) {
native_rotate(mNativeCanvasWrapper, degrees);
}
/**
* Preconcat the current matrix with the specified rotation.
*
* @param degrees The amount to rotate, in degrees
* @param px The x-coord for the pivot point (unchanged by the rotation)
* @param py The y-coord for the pivot point (unchanged by the rotation)
*/
public final void rotate(float degrees, float px, float py) {
translate(px, py);
rotate(degrees);
translate(-px, -py);
}
使用:
RectF rectf=new RectF(100, 100, 200, 200);
canvas.drawRect(rectf,mPaint);
//将画布旋转
mPaint.setColor(Color.YELLOW);
//第一个参数是旋转的角度 第二个参数是X的旋转坐标 第三个参数是Y的旋转坐标
canvas.rotate(45,100,100);
//旋转后重新绘制矩形
canvas.drawRect(rectf,mPaint);
效果:
1.4、斜拉画布
/**
* Preconcat the current matrix with the specified skew.
*
* @param sx The amount to skew in X
* @param sy The amount to skew in Y
* sx,sy倾斜度
*/
public void skew(float sx, float sy) {
native_skew(mNativeCanvasWrapper, sx, sy);
}
使用:
RectF rectf=new RectF(100, 100, 200, 200);
canvas.drawRect(rectf,mPaint);
//将画布旋转
mPaint.setColor(Color.YELLOW);
canvas.skew(1.73f,0);
//旋转后重新绘制矩形
canvas.drawRect(rectf,mPaint);
效果:
1.5、裁剪画布
RectF rectf=new RectF(200, 200, 400, 500);
canvas.drawRect(rectf,mPaint);
//进行裁剪
canvas.clipRect(new RectF(250, 250, 300, 400));
canvas.drawColor(Color.YELLOW);
效果:
上面这些大致就是Canvas的一些基本使用,学习记录于此。