withSaveLayer
inline fun Canvas.withSaveLayer(bounds: Rect, paint: Paint, block: () -> Unit)
Saves a copy of the current transform and clip on the save stack, and then creates a new group
which subsequent calls will become a part of. When the lambda is executed and the save stack is
popped, the group will be flattened into a layer and have the given paint
's Paint.colorFilter
and Paint.blendMode
applied.
This lets you create composite effects, for example making a group of drawing commands
semi-transparent. Without using Canvas.saveLayer
, each part of the group would be painted
individually, so where they overlap would be darker than where they do not. By using
Canvas.saveLayer
to group them together, they can be drawn with an opaque color at first, and
then the entire group can be made transparent using the Canvas.saveLayer
's paint.
Using saveLayer with clips
When a rectangular clip operation (from Canvas.clipRect
) is not axis-aligned with the raster
buffer, or when the clip operation is not rectalinear (e.g. because it is a rounded rectangle
clip created by Canvas.clipPath
), the edge of the clip needs to be anti-aliased.
If two draw calls overlap at the edge of such a clipped region, without using Canvas.saveLayer
,
the first drawing will be anti-aliased with the background first, and then the second will be
anti-aliased with the result of blending the first drawing and the background. On the other hand,
if Canvas.saveLayer
is used immediately after establishing the clip, the second drawing will
cover the first in the layer, and thus the second alone will be anti-aliased with the background
when the layer is clipped and composited (when lambda is finished executing).
Performance considerations
Generally speaking, Canvas.saveLayer
is relatively expensive.
There are a several different hardware architectures for GPUs (graphics processing units, the hardware that handles graphics), but most of them involve batching commands and reordering them for performance. When layers are used, they cause the rendering pipeline to have to switch render target (from one layer to another). Render target switches can flush the GPU's command buffer, which typically means that optimizations that one could get with larger batching are lost. Render target switches also generate a lot of memory churn because the GPU needs to copy out the current frame buffer contents from the part of memory that's optimized for writing, and then needs to copy it back in once the previous render target (layer) is restored.
See also:
Canvas.save
, which saves the current state, but does not create a new layer for subsequent commands.BlendMode
, which discusses the use ofPaint.blendMode
withsaveLayer
.