android 图层绘画分析,Android绘图之Canvas概念理解(5)

Canvas概述

前面讲解了Canvas能够绘制多种图形,但没有讲解Canvas的概念,想要理解canvas不容易,官方对Canvas这个类的介绍没有说太多,下面我说说我的理解,当然也是结合网上大神们的文章,下面我们从Canvas这个类的注释和方法的注释上来了解这个类。

Canvas 类上的注释

第一段注释(Canvas类上):

The Canvas class holds the "draw" calls. To draw something, you need

4 basic components: A Bitmap to hold the pixels, a Canvas to host

the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect,

Path, text, Bitmap), and a paint (to describe the colors and styles for the

drawing).

解释:

Canvas持有很多draw开头的方法,要想绘制一些东西,需要四个基本的元素:

1,一个保存像素的Bitmap

2,一个Canvas 调用drawxxx方法(画东西到bitmap)

3,要绘制的东西(矩形,路径,text,bitmap)

4,一个画笔

所以最终东西会被画到一个bitmap上,然后才渲染到屏幕上。

初始化方法:

//构造一个空的canvas,然后利用setBitmap设置一个bitmap,为canvas指定画图的画布,最终的东西都被绘制在bitmap上

public Canvas() ;

//所有的canvas的状态类似Layer,filters 和save/restore栈都会被重置,

//canvas的目标density也会更新匹配这个bitmap

public void setBitmap(@Nullable Bitmap bitmap)

//类似空参构造,这里直接传入bitmap构造Canvas

public Canvas(@NonNull Bitmap bitmap);

如何使用,想要直接使用可以直接重写view的onDraw方法,可以获取canvas.

Save函数注释

/**

Saves the current matrix and clip onto a private stack.

Subsequent calls to translate,scale,rotate,skew,concat or clipRect,

clipPath will all operate as usual, but when the balancing call to

restore() is made, those calls will be forgotten, and the settings that

existed before the save() will be reinstated.

@return The value to pass to restoreToCount() to balance this save()

*/

public int save() ;

Save函数会保存当前canvas的matrix和Clip信息到stack中,save之后调用 translate,scale,rotate,skew,concat or clipRect,clipPath都会作用于当前Canvas,当调用restore函数时这些操作将被遗忘,会恢复save之前的canvas状态。

saveLayer 注释

多个savelayer函数注释相同,只选择其中一个。

/* This behaves the same as save(), but in addition it allocates and

* redirects drawing to an offscreen bitmap.

*

Note: this method is very expensive,

* incurring more than double rendering cost for contained content. Avoid

* using this method, especially if the bounds provided are large. It is

* recommended to use a {@link android.view.View#LAYER_TYPE_HARDWARE hardware layer} on a View

* to apply an xfermode, color filter, or alpha, as it will perform much

* better than this method.

*

* All drawing calls are directed to a newly allocated offscreen bitmap.

* Only when the balancing call to restore() is made, is that offscreen

* buffer drawn back to the current target of the Canvas (either the

* screen, it's target Bitmap, or the previous layer).

*

*/

public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint, @Saveflags int saveFlags) ;

翻译:saveLayer函数类似save函数的作用,但调用了saveLayer函数会分配并生成一个屏幕以外的bitmap(意思就是不在原来的bitmap上),之后的所有操作都是在这个新的offscreen bitmap上。

savelayer这是一个非常耗费性能的方法,会导致绘制相同的内容渲染时耗费两倍多的资源。当需要的形状很大时(超屏幕)禁止使用这个方法。当应用一个xfermode ,color filter或者alpha是推荐使用硬件加速会表现更好。

观点1

从上面的这些注释可以推断的是新生成了bitmap,而一个Canvas只能对应一个bitmap(推断),所以调用saveLayer相当于新生成了一个Canvas,新的Canvas有一个默认连接的Bitmap。新生成的Canvas会修改函数中canvas的指向,所以再次利用Canvas调用函数时将作用于新生成的canvas上。(ps:这里描述新生成Canvas只是猜测,也可能是改变了Canvas对Bitmap的引用,说了会新生成一个bitmap,并且所有的操作类似clip都不会影响原来的canvas,clip本来就是对canvas的操作。所以最终很有可能是调用saveLayer改变了Canvas对Bitmap的引用)

调用drawXXX函数生成新的layer最终都会绘制到新生成的bitmap,直到调用restore()函数,新的bitmap会被绘制到原始Canvas的连接的目标上)(可能是bitmap,也可能是前一个Layer)。

这里总结一下:

所有的东西都是绘制在bitmap上的,canvas是一个虚拟的概念,它连接着一个bitmap,东西都绘制在bitmap上,每次调用drawxx函数都生成一个透明图层(layer),最终都会覆盖绘制在bitmap上,经过渲染才显示在屏幕上,Canvas可以比屏幕大很多,但是超出屏幕范围的图像是不会显示出来的,我们也就看不到。

SaveLayer中提到了图层,什么是layer呢?

Canvas 的setBitmap函数上有一段注释:

Specify a bitmap for the canvas to draw into. All canvas state such as layers, filters, and the save/restore stack are reset.

调用setBitmap时,会为canvas连接一个bitmap,所有的canvas的状态类似layers,filters和save/restore 栈都将重置。所以layer是canvas的一种状态,可以保存,它可以承载clip,matrix,图形,颜色等信息,所以每次调用draw方法都会生成一个新的图层layer。调用draw生成的图层最终会覆盖在它所依附的bitmap上。调用restore()、resoreToCount()函数以后,将恢复到Canvas对应的最原始的bitmap上进行绘制。

我们对layer和canvas对应的bitmap有了理解,bitmap可以看成我们平时说的画布,最终的东西都是绘制在这上面的,每次调用drawXXX方法会生成一个新的透明layer,东西被绘制在layer上,然后最终会被绘制在bitmap上。

调用savelayer函数会生成新的Bitmap,所以我认为调用saveLayer会生成一个新的Canvas连接一个新的Bitmap(或者改变了原来Canvas的bitmap的引用指向),然后再调用drawXX函数也会生成新的layer,但这个layer会被绘制到新生成的Bitmap上,其他所有的rotate,clip等操作,都会作用在新的Canvas上(或者新指向的bitmap上),不会影响原始的Canvas(原始bitmap),直到调用restore函数,才会被最终绘制到原始Canvas连接的bitmap上。所以canvas是一个包含了多种状态(clip,matrix等)的类,它有点类似坐标系(规定绘制图形的位置),所有的操作都不会影响已经绘制在上面的图形,会连接一个Bitmap,所有的东西最终都会被绘制在Bitmap上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值