画布Canvas

屏幕显示与Canvas的关系:

很多人一直以为显示所绘图形的屏幕就是Canvas,其实这是一种非常错误的理解,比如下面这段代码

举例:

//构造两个画笔,一个红色,一个绿色
Paint paint_green = generatePaint(Color.GREEN, Paint.Style.STROKE, 3);
Paint paint_red = generatePaint(Color.RED, Paint.Style.STROKE, 3);
//构造一个矩形
Rect rect1 = new Rect(0, 0, 400, 200);
//在平移画布前用绿色画出
canvas.drawRect(rect1, paint_green);
//在平移画布后,再用红色画出
canvas.translate(100, 100);
canvas.drawRect(rect1, paint_red);

private Paint generatePaint(int color, Paint.Style style, int width) {
    //设置画笔的样式
    Paint paint = new Paint();
    paint.setColor(color);
    paint.setStyle(style);
    paint.setStrokeWidth(width);
    return paint;
}

如图:

注意事项:

在Canvas上虽然能画图,但超出了屏幕的显示范围,是不会显示的

对画布进行操作:

在对画布操作前,不能对已经画出的形状做影响,也就是画布操作只能影响到之后的绘画元素,画布操作前的绘画是不可逆的,在对画布进行变换操作时,最好在操作完之后利用save()和restore()函数将画布状态复原

1.画布平移当前绘图:

功能说明:
画布的原始状态是以左上角点为原点,向右是X轴正方向,向下是Y轴正方向
画布的左上角是坐标的原点(0,0),当画布平移后,平移后的位置作为新的原点(0,0)计算

构造函数:

void translate(float dx, float dy)

参数:

dx:                       水平方向平移的距离,正数为向右,负数为向左
dy:                       垂直方向平移的距离,正数为向下,负数为向上

示例:

Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
canvas.translate(100,100);
Rect rect1 = new Rect(0, 0, 400, 200);
canvas.drawRect(rect1, paint);

如图:

图一是平移前的矩形坐标位置,图二是平移后的相同矩形坐标位置

2.画布旋转当前绘图:

功能说明:

画布里的元素形状默认是围绕画布原点来绘制的,旋转画布,会改变起始点位置,所以容易产生错觉,以为是元素旋转了,其实我们旋转的是画布,因此在画布上绘制的元素看起来都是旋转的

构造函数:

void rotate(float degrees)
void rotate(float degrees, float px, float py)

示例:

//设置画笔为绿色
Paint paint_green = generatePaint(Color.GREEN, Paint.Style.FILL, 5);
//设置画笔为红色
Paint paint_red = generatePaint(Color.RED, Paint.Style.STROKE, 5);
Rect rect1 = new Rect(300, 10, 500, 100);
//先画出原轮廓
canvas.drawRect(rect1, paint_red);
//顺时针旋转画布30度
canvas.rotate(30);
//再画出旋转后的轮廓
canvas.drawRect(rect1, paint_green);

generatePaint

如图:

红色为画布旋转前的矩形,绿色为画布旋转后的矩形

3.画布缩放当前绘图:

功能说明:
按比例缩放当前绘图的尺寸

构造函数:

public void scale(float sx, float sy)
public void scale(float sx, float sy, float px, float py)

参数:

sx:                                              小于1代表缩小,大于1代表放大
sy:                                              小于1代表缩小,大于1代表放大
px:                                              缩放中心X位置
py:                                              缩放中心Y位置

示例:

//设置画笔设置为绿色画出初始矩形
Paint paint_green = generatePaint(Color.GREEN, Paint.Style.STROKE, 5);
//设置画笔设置为红色画出缩放后矩形
Paint paint_red = generatePaint(Color.RED, Paint.Style.STROKE, 5);
//构造一个矩形
Rect rect1 = new Rect(10, 10, 200, 100);
//先用绿色画出初始矩形
canvas.drawRect(rect1, paint_green);
//对画布之后的绘图进行缩放,X缩小0.5,Y放大0.5
canvas.scale(0.5f, 1.5f);
//画布缩放后的矩形
canvas.drawRect(rect1, paint_red);

如图:

绿色为初始矩形,红色为缩放后矩形

4.画布倾斜当前绘图:

功能说明:
可将当前绘画元素进行倾斜

构造函数:

void skew(float sx, float sy)

参数:

sx:                           将画布在X轴方向上倾斜相应的角度,sx为倾斜角度的正切值,正数为向右倾斜,负数为向左倾斜
sy:                           将画布在Y轴方向上倾斜相应的角度,sy为倾斜角度的正切值,正数为向下倾斜,负数为向上倾斜

示例:

//声明绿色画笔
Paint paint_green = generatePaint(Color.GREEN, Paint.Style.STROKE, 5);
//声明红色画笔
Paint paint_red = generatePaint(Color.RED, Paint.Style.STROKE, 5);
//声明一个矩形
Rect rect1 = new Rect(10, 10, 200, 100);
//先用绿色画出未倾斜的矩形
canvas.drawRect(rect1, paint_green);
//x轴向右倾斜,Y轴不变
canvas.skew(0.5f, 0);
//再用红色画出倾斜后的矩形
canvas.drawRect(rect1, paint_red);

如图:

绿色为未倾斜原图,红色为X轴向右倾斜后的图

5.裁剪画布(clip系列函数):

功能说明:
裁剪画布是利用clip系列函数,通过与Rect/Path/Region取交,并,差等集合运算来获得最新画布形状,除调用save()/restore()函数以外,这个操作是不可逆的,一旦Canvas被裁剪,就不能恢复
注意:
在使用clip系列函数时,需要禁用硬件加速功能,如果不禁用硬件加速功能,将不会产生任何效果

禁用硬件加速:
setLayerType(LAYER_TYPE_SOFTWARE,null);

clip系列函数如下:

boolean clipPath(Path path)
boolean clipPath(Path path, Region.Op op)
boolean clipRect(Rect rect, Regopn.Op op)
boolean clipRect(RectF rect, Region.Op op)
boolean clipRect(int left, int top, int right, int bottom)
boolean clipRect(float left, float top, float right, float bottom)
boolean clipRect(RectF rect)
boolean clipRect(float left, float top, float right, float bottom, Region.Op op)
boolean clipRect(Rect rect)
boolean clipRect(Region region)
boolean clipRect(Region region, Region.Op op)

以clipRect()函数来讲示例:

//先把画布用红色背景填充
canvas.drawColor(Color.RED);
//再把画布进行指定大小裁剪
canvas.clipRect(new Rect(100, 100, 200, 200));
//从新定义画布背景色
canvas.drawColor(Color.GREEN);

如图:

红色背景图实际为填满手机屏幕图,绿色背景为裁剪后的画布区域

画布的保存与恢复:

功能说明:

对画布的操作默认是不可逆的,该函数可以对画布的状态进行实时保存和恢复

1.save()和restore()函数

构造函数:

int save()                                返回值是当前所保存的画布所在栈的索引                         
void restore()

函数介绍:

save():                                   每次调用save()函数,都会先保存当前画布的状态,然后将其放入特定的栈中
restore():                               每次调用restore()函数,都会把栈中顶层的画布状态取出来,并按这个状态继续作画

示例:

//保存当前画布大小到栈中,既整屏
canvas.save();
canvas.clipRect(new Rect(100, 100, 800, 800));
canvas.drawColor(Color.GREEN);
//从栈中恢复顶层保存的画布
canvas.restore();
canvas.drawColor(Color.RED);

如图:

还是整屏的画布状态

注意事项:
每调用一次save()函数,都会将当前的画布状态保存到栈中,多次调用save(),保存顺序为1/2/3/4
当调用restore()取出来的时候,依次从栈顶的4/3/2/1取,save()函数可连续调用,restore()函数可连续取

2.restoreToCount(int saveCount)函数

功能说明:
上面讲述每次调用restore()函数,只会将顶层画布取出,在save保存所在栈索引时,可将索引保存起来,利用该函数取出指定画布状态

注意事项:
restoreToCount()函数的用法就是一直出栈,直到指定索引的画布出栈为止,对于在某部分顶层栈的画布,可能会丢失

构造函数:

public void restoreToCount(int saveCount);

参数:

saveCount:                                      指定栈中索引

示例:

//先将整屏背景色填充为红色
canvas.drawColor(Color.RED);
//保存整瓶画布状态
int c1 = canvas.save();
//保存画布颜色为Color.GREEN
canvas.clipRect(new Rect(100, 100, 800, 800));
canvas.drawColor(Color.GREEN);
int c2 = canvas.save();
//保存画布颜色为BLUE
canvas.clipRect(new Rect(200, 200, 700, 700));
canvas.drawColor(Color.BLUE);
int c3 = canvas.save();
//保存画布颜色为BLACK
canvas.clipRect(new Rect(300, 300, 600, 600));
canvas.drawColor(Color.BLACK);
int c4 = canvas.save();
canvas.clipRect(new Rect(400, 400, 500, 500));
canvas.drawColor(Color.WHITE);
//先取第一个,既整屏画布
canvas.restoreToCount(c1);
//颜色填充为黄色
canvas.drawColor(Color.YELLOW);
//再取第二个裁剪画布
canvas.restoreToCount(c2);
//颜色填充为黑灰色
canvas.drawColor(Color.DKGRAY);

如图:

图为整屏黑灰色,因为先取了C1,在取到C1之后,C2已经被遍历丢失掉,所以又取了C2,没有取出,画布当前还是在C1状态,这个时候填充背景色为黑灰色,所以最后效果为C1画布状态的黑灰色

画布背景颜色设置:

构造函数:

Canvas.drawColor(int color)
Canvas.drawARGB(int a,int r,int g,intb)
Canvas.drawRGB(int r,int g,int b)

参数:

color:                    取值必须是8位的0xAARRGGBB样式颜色值
a,r,g,b:                 分别传入A、R、G、B分量
r,g,b:                    只允许传入R、G、B分量,透明度值取255(不透明)

示例:

比如,将画布默认填充为紫色:

canvas.drawRGB(255,0,255);

这里使用的是十进制数据,当然,如果使用十六进制数值更可观:

canvas.drawRGB(0xFF,0x00,0xFF);

这个颜色值对应另外两个函数写法如下:

canvas.drawColor(0xFFFF00FF);

canvas.drawARGB(0xFF,0xFF,0,0xFF);

画直线:

构造函数:

Canvas.drawLine(float startX,float startY,float stopX,float stopY);

参数:

startX: 起始点X坐标(左)

startY: 起始点Y坐标(上)

stopX: 终点X坐标(右)

stopY: 终点Y坐标(下)

示例如下:

canvas.drawLine(100,100,200,200,paint);

直线的粗细与画笔的Paint.setStyle是没有关系的,当设置画笔不同的Paint.setStrokeWidth时,才与粗细有直接关系;

画矩形:

构造函数:

Canvas.drawRect(Rect rect,Paint paint)
Canvas.drawRect(float left,float top,float right,float bottom,Paint paint)
Canvas.drawRect(RectF rectf,Paint paint)

关键参数:

rect:                                         矩形工具类
paint:                                       画笔工具类
(left,top,right,bottom):              分别对应矩形的左上右下
rectf:                                        矩形工具类

RectF、Rect:

这两个参数都是矩形工具类,根据4个点构造出一个矩形结构,RectF与Rect中的方法、成员变量完全一样,唯一不同的是RectF参数是float类型的,而Rect参数是int类型的 

示例:

//直接构造

canvas.drawRect(10,10,100,100,paint);

//使用RectF构造

RectF rect=new RectF(210f,10f,300f,100f);

canvas.drawRect(rect,paint);

画圆角矩形:

构造函数:

Canvas.drawRoundRect(RectF rect,float rx,float ry,Paint paint)

参数:

rect:              要绘制的矩形工具类
rx:                  生成圆角的X轴半径
ry:                  生成圆角的Y轴半径
paint:            画笔工具类
return:           void

示例:

Paint paint=new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(15);

paint.setAntiAlias(true);    //抗锯齿
RectF rect=new RectF(100,10,300,100);
canvas.drawRoundRect(rect,20,20,paint);

效果如图:

画圆: 

构造函数:

canvas.drawCircle(float cx,float cy,float radius,Paint paint)

参数:

cx:           圆的X轴坐标
cy:           圆的y轴坐标
radius:     圆的半径
paint:      画笔工具类
return:     void

示例:

//设置画笔的基本属性
Paint paint = new Paint();
paint.setColor(0XFFFF0000);      //设置画笔颜色为红色
paint.setStyle(Paint.Style.FILL);   //设置填充样式,该样式为仅填充内部
paint.setStrokeWidth(50);     //设置画笔宽度,默认为px
//画圆
canvas.drawCircle(190, 200, 150, paint);    //150为圆的半径,默认为px
paint.setColor(0X7EFFFF00);      //设置画笔颜色为带透明度的黄色
canvas.drawCircle(190, 200, 100, paint);   //100为圆的半径,默认为px

效果图:

画弧形: 

构造函数:

Canvas.drawArc(RecfF oval,float startAngle,float sweepAngle,boolean useCenter,Paint paint)

弧是椭圆的一部分,而椭圆是根据矩形来形成的,所以弧也是根据矩形来形成的;

参数:
oval:                 生成椭圆的矩形工具类
startAngle:       弧开始的角度,已X轴正方向为0° 
sweepAngle:    弧持续的角度
useCenter:       是否有弧的两边,为true时,表示带有两边,为false时,只有一条弧形
return:              void

示例:

Paint paint=new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
//带两边
RectF rect1=new RectF(10,10,100,100);
canvas.drawArc(rect1,0,90,true,paint);
//不带两边
RectF rect2=new RectF(110,10,200,100);
canvas.drawArc(rect2,0,90,false,paint);

效果图:

左侧为带两边的弧,右侧为不带两边的弧;

画路径:

构造函数:

canvas.drawPath(Path path,Paint paint)

画笔所画出来的一段不间断的轨迹就是路径;

参数:
path:                路径工具类
paint:               画笔工具类

return:             void

直线示例:

        Paint paint = new Paint();
        paint.setColor(Color.RED);  //设置画笔颜色
        paint.setStyle(Paint.Style.FILL);//填充样式改为描边
        paint.setStrokeWidth(5);//设置画笔宽度
        Path path = new Path();
        path.moveTo(10, 10); //设定路径的起始点(只是起始位置,无任何轨迹)
        path.lineTo(10, 100);//画第一条起始点的终点,也是第二条直线的起始点
        path.lineTo(300, 100);//画第二条直线
        path.close();//闭环

        canvas.drawPath(path, paint);

如果连续画了几条直线,但没有形成闭环,那么调用close()函数会将路径首尾点连接起来,形成闭环;

调用close效果图:

未调用close图:

画文字: 

构造函数:

Canvas.drawText(char[] text, int index, int count, float x, float y, Paint paint)
Canvas.drawText(String text, float x, float y, Paint paint)
Canvas.drawText(String text, int start, int end, float x, float y, Paint paint)
Canvas.drawText(CharSequence text, int start, int end, float x, float y, Paint paint)

功能:画文字内容,文字的样式主要通过Paint类设置;

参数:
text:                  文本内容
index:               指定起始绘制字符的位置
count:               指定从起始绘制字符开始绘制几个字符
x:                      开始的X坐标
y:                      开始的Y坐标
paint:               画笔工具类
start:                 表示起始绘制字符所在字符串中的索引
end:                  表示结束绘制字符所在字符串中的索引
return:               void

示例:

Paint paint=new Paint();
paint.setColor(Color.RED);    //设置文字颜色
paint.setTextSize(80);       //设置文字大小
canvas.drawText("床前明月光", 10,100, paint);

效果图:

画文字逐个指定文字位置:

构造函数:

void drawPosText(String text, float[] pos, Paint paint)
void drawPosText(char[] text, int index, int count, float[] pos, Paint paint)

功能:对每一个文字都定义不同的位置;

参数:
text:                          要绘制的字符串
pos:                          要绘制的每个文字的具体位置,同样两两一组,如{x1,y1,x2,y2,x3,y3}
paint:                       Paint画笔工具类
index:                       第一个要绘制的文字的索引
count:                       要绘制的文字的总数

示例:

Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setTextSize(80);
float[] pos = new float[]{80, 100, 80, 200, 80, 300, 80, 400};
canvas.drawPosText("窗前明月", pos, paint);

效果图:

沿路径绘制文字:

构造函数:

void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)
void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset)

功能:沿着画的路径绘制文字;

参数:
text:                              文本内容
path:                            Path工具类
hOffset:                        文字起始路径以路径起始位置水平偏移量
vOffset:                        文字与路径的垂直偏移
paint:                           Paint画笔工具类
index:                           第一个要绘制的文字的索引
count:                          要绘制的文字的总数

示例:

Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(2);
paint.setTextSize(45);
paint.setStyle(Paint.Style.STROKE);
Path circlePath2 = new Path();
circlePath2.addCircle(600, 300, 150, Path.Direction.CCW);
canvas.drawPath(circlePath2, paint);     //绘制出路径圆形
//绘制原始文字与偏移文字
String string = "窗前明月光,疑是地上霜";
paint.setColor(Color.GREEN);
//沿着circlePath2路径绘制文字
canvas.drawTextOnPath(string, circlePath2, 180, 30, paint);

效果图:

示例图讲解:

图1的hOffset,voffset都为0,图二的hOffset,vOffset分别为180,30,hOffset控制的是沿着路径文字起始位置与路径起始位置的水平偏移量,vOffset是原有Y度直径基础上,增加或减少偏移量,负数是减少,正数是增加,图上30,文字绘制扩张到了外层线

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值