自定义viewcanvas使用

Posted 一介闲休

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义viewcanvas使用相关的知识,希望对你有一定的参考价值。

欲先攻其事必先利其器,想要做好自定义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,这下明白了吧!

以上是关于自定义viewcanvas使用的主要内容,如果未能解决你的问题,请参考以下文章

小玩意--自定义log记录

自定义View之无限大图轮播ShufBanner

WordPress 自定义帖子类型无限循环

使用自定义积木增强Scratch无限循环积木功能

使用自定义积木增强Scratch无限循环积木功能

自定义 Spring Security 应用程序中的无限循环