自定义view(1)canvas使用

欲先攻其事必先利其器,想要做好自定义view,就必须先将canvas掌握,面对canvas,我们在心中必先要有个这样的意识,canvas是无限大的,而之所以我们看到了只有屏幕大小,那是屏幕给我们带来的迷惑,废话不多说,今天我们主要来聊canvas中常用用法,translate,rotate,save,restore等功能,估计大伙都觉得这几个功能很简单嘛,网上随便一搜一大把,其实到了一些真正细节的东西都含糊其词了。
是不是大家之前一直存在一下观点:
translate移动改变了canvas的坐标,rotate(degress)改变了canvas的坐标角度,而rotate(degress,x,y)效果相当于translate(x,y)+rotate(degress)但没有改变canvas坐标?真相是否如此,咱们看代码和图
先图个矩形且画出坐标:

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mPaint.setColor(Color.GREEN);
        canvas.drawRect(0,0,100,100,mPaint);
        //画出坐标系
        drawAxis(canvas,Color.RED);


    }
private void drawAxis(Canvas canvas, @ColorInt int color){
        mPaint.setStrokeWidth(10);
        mPaint.setColor(color);
        canvas.drawLine(0,0,400,0,mPaint);
        canvas.drawLine(0,0,0,400,mPaint);
    }

这里写图片描述

现在我们执行translate方法

        canvas.translate(500,500);
        mPaint.setColor(Color.GREEN);
        canvas.drawRect(0,0,100,100,mPaint);
        drawAxis(canvas,Color.RED);

这里写图片描述
这个没问题,translate执行后,坐标系的确移动了,现在我们来看rotate(degress)

        canvas.rotate(45);
        mPaint.setColor(Color.BLACK);
        canvas.drawRect(0,0,100,100,mPaint);
        drawAxis(canvas,Color.BLUE);

这里写图片描述
坐标系也的确旋转了,那我们接着来看下rotate(45,x,y)和translate(x,y)+rotate(45)效果是不是一样?前者是否改变了原来的坐标系呢?
其实translate(x,y)+rotate(45)的效果前面我们已经看到了,他的确既改变坐标又改变了角度,接下来我们看看rotate(45,x,y)是不是和前者重合?

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //为看到更好的效果,我们统一将坐标移动到(500,500)
        canvas.translate(500,500);
        mPaint.setColor(Color.GREEN);
        canvas.drawRect(0,0,100,100,mPaint);
        //画出坐标系
        drawAxis(canvas,Color.RED);
        //移动
        canvas.translate(500,500);
        mPaint.setColor(Color.GREEN);
        canvas.drawRect(0,0,100,100,mPaint);
        drawAxis(canvas,Color.RED);
        //旋转
        canvas.rotate(45);
        mPaint.setColor(Color.BLACK);
        canvas.drawRect(0,0,100,100,mPaint);
        drawAxis(canvas,Color.BLUE);
        //到这已经改变了角度和坐标,我们先复原
        canvas.rotate(-45);
        canvas.translate(-500,-500);
        //再来重新rotate(45,500,500);
        mPaint.setColor(Color.GRAY);
        canvas.rotate(45,500,500);
        canvas.drawRect(0,0,100,100,mPaint);
        drawAxis(canvas,Color.BLACK);
    }

为了更好地看到效果,我们将初始坐标移动至(500,500),效果如下:
这里写图片描述
什么情况,怎么rotate(45)+translate(500,500)和rotate(45,500,500)效果完全不同呢,而且后者画的东西完全不符合逻辑嘛,是不是颠覆我们的想法?究竟rotate(45,500,500)做了什么?直接上源码:

public final void  rotate(float degrees, float px, float py) {
     translate(px, py);
     rotate(degrees);
     translate(-px, -py);
    }

看到没,源码是在移动坐标旋转角度后,再回复坐标,此时还能恢复不?答案是肯定不能的,除非先恢复坐标系的角度,然后再恢复,那才能恢复到原来的坐标点,现在知道原因了吧。

接着我们来看下,save和restore,这玩意究竟什么用呢?听说夹在这两个玩意中间的任何操作都没有改变原始坐标系,究竟是不是这样?直接上demo

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //为看到更好的效果,我们统一将坐标移动到(500,500)
        canvas.translate(500,500);
        mPaint.setColor(Color.GREEN);
        canvas.drawRect(0,0,100,100,mPaint);
        //画出坐标系
        drawAxis(canvas,Color.RED);
        canvas.save();
        //移动
        canvas.translate(500,500);
        mPaint.setColor(Color.GREEN);
        canvas.drawRect(0,0,100,100,mPaint);
        drawAxis(canvas,Color.RED);
        //旋转
        canvas.rotate(45);
        mPaint.setColor(Color.BLACK);
        canvas.drawRect(0,0,100,100,mPaint);
        drawAxis(canvas,Color.BLUE);
        canvas.restore();
        //再次画图
        mPaint.setColor(Color.GRAY);
        canvas.drawRect(0,0,60,60,mPaint);
        drawAxis(canvas,Color.BLACK);
    }

这里写图片描述
看到没,在save和restore之间做的图,直接显示在屏幕上了,但是在save之前和restore之后的坐标系真没有改变,是不是恨好奇?
其实,用个ps的人都知道,save和restore之间其实是在新的层上面了,save和restore之外的部分才是同层上做操作,两层的操作肯定不干扰了,ok,这下明白了吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值