自定义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使用的主要内容,如果未能解决你的问题,请参考以下文章