ViewStrokeRenderer


public final class ViewStrokeRenderer


Helps developers using Android Views to draw androidx.ink.strokes.Stroke objects in their UI, in an easier way than using CanvasStrokeRenderer directly. Construct this once for your View and reuse it during each View.onDraw call.

This utility is valid as long as View.onDraw

  1. Does not call Canvas.setMatrix.

  2. Does not modify Canvas transform state prior to calling drawWithStrokes.

  3. Does not use android.graphics.RenderEffect, either setting it on this View or a subview using View.setRenderEffect, or by calling Canvas.drawRenderNode using a android.graphics.RenderNode that has been configured with android.graphics.RenderNode.setRenderEffect. Developers who want to use android.graphics.RenderEffect in conjunction with androidx.ink.strokes.Stroke rendering must use CanvasStrokeRenderer.draw directly.

Example:

class MyView(context: Context) : View(context) {
private val viewStrokeRenderer = ViewStrokeRenderer(myCanvasStrokeRenderer, this)

override fun onDraw(canvas: Canvas) {
viewStrokeRenderer.drawWithStrokes(canvas) { scope ->
canvas.scale(myZoomLevel)
canvas.rotate(myRotation)
canvas.translate(myPanX, myPanY)
scope.drawStroke(myStroke)
// Draw other objects including more strokes, apply more transformations, etc.
}
}
}

Summary

Public constructors

ViewStrokeRenderer(
    @NonNull CanvasStrokeRenderer canvasStrokeRenderer,
    @NonNull View view
)

Public methods

final void
drawWithStrokes(
    @NonNull Canvas canvas,
    @NonNull Function1<@NonNull StrokeDrawScopeUnit> block
)

Kotlin developers should call this at the beginning of View.onDraw and perform their Canvas manipulations within its scope.

final void
drawWithStrokes(
    @NonNull Canvas canvas,
    @NonNull Function2<@NonNull Canvas, @NonNull StrokeDrawScopeUnit> block
)

Java developers should call this at the beginning of View.onDraw and perform their Canvas manipulations within its scope.

Public constructors

ViewStrokeRenderer

Added in 1.0.0-alpha02
public ViewStrokeRenderer(
    @NonNull CanvasStrokeRenderer canvasStrokeRenderer,
    @NonNull View view
)

Public methods

drawWithStrokes

Added in 1.0.0-alpha02
public final void drawWithStrokes(
    @NonNull Canvas canvas,
    @NonNull Function1<@NonNull StrokeDrawScopeUnit> block
)

Kotlin developers should call this at the beginning of View.onDraw and perform their Canvas manipulations within its scope.

For example:

viewStrokeRenderer.drawWithStrokes(canvas) { scope ->
canvas.scale(...) // or concat, or translate, or rotate, etc.
scope.drawStroke(stroke)
// Repeat with other strokes, draw other things to the canvas, etc.
}

Java callers should prefer to use the non-inline overload of drawWithStrokes with a non-capturing lambda or an object that is allocated once and reused.

drawWithStrokes

Added in 1.0.0-alpha02
public final void drawWithStrokes(
    @NonNull Canvas canvas,
    @NonNull Function2<@NonNull Canvas, @NonNull StrokeDrawScopeUnit> block
)

Java developers should call this at the beginning of View.onDraw and perform their Canvas manipulations within its scope.

The structure of the callback in this non-inline version makes it easier for Java callers to write performant code, since forwarding the value of canvas allows a lambda to be non-capturing, thereby avoiding an allocation of the lambda on every frame.

For example:

viewStrokeRenderer.drawWithStrokes(canvas, (scopedCanvas, scope) -> {
// Make sure to use `scopedCanvas` rather than `canvas` in this lambda!
scopedCanvas.scale(...); // or concat, or translate, or rotate, etc.
scope.drawStroke(stroke);
// Repeat with other strokes, draw other things to the canvas, etc.
});

Alternatively, the callback could be an object that is allocated once and reused.

Kotlin callers should prefer to use the inline overload of drawWithStrokes, as it better guarantees that the lambda argument will not cause an allocation.