Android自定义View学习四---Canvas画布操作

Canvas之画布操作

内容来自:安卓自定义View进阶-Canvas之画布操作

基本操作

位移

translate是坐标系的移动,位移是基于当前位置移动,而不是每次基于屏幕左上角的(0,0)点移动

        // 绘制矩形
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(new Rect(0, 0, 200, 200), mPaint);

        // 在坐标原点绘制一个黑色圆形
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.translate(200, 200);
        canvas.drawCircle(100, 100, 100, mPaint);

        // 在坐标原点绘制一个蓝色圆形
        mPaint.setColor(Color.BLUE);
        canvas.translate(200,200);
        canvas.drawCircle(0,0,100,mPaint);

位移

缩放(scale)

缩放提供了两个方法,如下:

public void scale (float sx, float sy)

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

缩放的中心默认为坐标原点,而缩放中心轴就是坐标轴,第二个方法的pxpy,用来控制缩放中心位置

// 将坐标系原点移动到画布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形区域

mPaint.setColor(Color.BLACK);           // 绘制黑色矩形
canvas.drawRect(rect,mPaint);

canvas.scale(0.5f,0.5f);                // 画布缩放

mPaint.setColor(Color.BLUE);            // 绘制蓝色矩形
canvas.drawRect(rect,mPaint);

缩放01

使用第二种方法让缩放中心位置稍微改变一下,如下:

// 将坐标系原点移动到画布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形区域

mPaint.setColor(Color.BLACK);           // 绘制黑色矩形
canvas.drawRect(rect,mPaint);

canvas.scale(0.5f,0.5f,200,0);          // 画布缩放  <-- 缩放中心向右偏移了200个单位

mPaint.setColor(Color.BLUE);            // 绘制蓝色矩形
canvas.drawRect(rect,mPaint);

缩放02

当缩放比例为负数的时候会根据缩放中心轴进行翻转

// 将坐标系原点移动到画布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形区域

mPaint.setColor(Color.BLACK);           // 绘制黑色矩形
canvas.drawRect(rect,mPaint);


canvas.scale(-0.5f,-0.5f);          // 画布缩放

mPaint.setColor(Color.BLUE);            // 绘制蓝色矩形
canvas.drawRect(rect,mPaint);

缩放03

和位移(translate)一样,缩放也是可以叠加的,如下的例子:

        // 将坐标系原点移动到画布正中心
        canvas.translate(mWidth / 2, mHeight / 2);

        RectF rect = new RectF(-400,-400,400,400);

        for (int i = 0; i < 20; i++) {
            canvas.scale(0.9f, 0.9f);
            canvas.drawRect(rect, mPaint);
        }

缩放04

旋转

旋转提供了两种方法:

public void rotate (float degrees)

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

第二种方法多出来的两个参数依旧是控制旋转中心点的

默认的旋转中心依旧是坐标原点:

// 将坐标系原点移动到画布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形区域

mPaint.setColor(Color.BLACK);           // 绘制黑色矩形
canvas.drawRect(rect,mPaint);

canvas.rotate(180);                     // 旋转180度 <-- 默认旋转中心为原点

mPaint.setColor(Color.BLUE);            // 绘制蓝色矩形
canvas.drawRect(rect,mPaint);

旋转01

改变旋转中心位置:

// 将坐标系原点移动到画布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形区域

mPaint.setColor(Color.BLACK);           // 绘制黑色矩形
canvas.drawRect(rect,mPaint);

canvas.rotate(180,200,0);               // 旋转180度 <-- 旋转中心向右偏移200个单位

mPaint.setColor(Color.BLUE);            // 绘制蓝色矩形
canvas.drawRect(rect,mPaint);

旋转02

同样旋转也可以叠加

// 将坐标系原点移动到画布正中心
canvas.translate(mWidth / 2, mHeight / 2);

canvas.drawCircle(0,0,400,mPaint);          // 绘制两个圆形
canvas.drawCircle(0,0,380,mPaint);

for (int i=0; i<=360; i+=10){               // 绘制圆形之间的连接线
   canvas.drawLine(0,380,0,400,mPaint);
   canvas.rotate(10);
}

旋转03

skew

skew只提供了一种方法

public void skew (float sx, float sy)
  • sx - 将画布在x方向上倾斜相应的角度,sx倾斜角度的tan
  • sy - 将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan
// 将坐标系原点移动到画布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,0,200,200);   // 矩形区域

mPaint.setColor(Color.BLACK);           // 绘制黑色矩形
canvas.drawRect(rect,mPaint);

canvas.skew(1,0);                       // 水平错切 <- 45度

mPaint.setColor(Color.BLUE);            // 绘制蓝色矩形
canvas.drawRect(rect,mPaint);

skew01

save和restore

我的理解,类似于iOS的CGContextSaveGStateCGContextRestoreGState

相关API简介
save把当前的画布的状态进行保存,然后放入特定的栈中
saveLayerXxx新建一个图层,并放入特定的栈中
restore把栈中最顶层的画布状态取出来,并按照这个状态恢复当前的画布
restoreToCount弹出指定位置及其以上所有的状态,并按照指定位置的状态进行恢复
getSaveCount获取栈中内容的数量(即保存次数)

状态栈

状态栈可以存储画布状态和图层状态

状态栈

save

save 有两种方法:

// 保存全部状态
public int save ()

// 根据saveFlags参数保存一部分状态
public int save (int saveFlags)

可以看到第二种方法比第一种多了一个saveFlags参数,使用这个参数可以只保存一部分状态,更加灵活。saveFlags参数,参见下表

名称简介
ALL_SAVE_FLAG默认,保存全部状态
CLIP_SAVE_FLAG保存剪辑区
CLIP_TO_LAYER_SAVE_FLAG剪裁区作为图层保存
FULL_COLOR_LAYER_SAVE_FLAG保存图层的全部色彩通道
HAS_ALPHA_LAYER_SAVE_FLAG保存图层的alpha(不透明度)通道
MATRIX_SAVE_FLAG保存Matrix信息( translate, rotate, scale, skew)

常用格式

save();      //保存状态
...          //具体操作
restore();   //回滚到之前的状态
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值