InProgressShapesView
public final class InProgressShapesView<ShapeSpecT extends Object, InProgressShapeT extends InProgressShape<@NonNull ShapeSpecT, @NonNull CompletedShapeT>, CompletedShapeT extends Object> extends FrameLayout
| java.lang.Object | ||||
| ↳ | android.view.View | |||
| ↳ | android.view.ViewGroup | |||
| ↳ | android.widget.FrameLayout | |||
| ↳ | androidx.ink.authoring.InProgressShapesView |
Displays in-progress shapes, as defined by a ShapeWorkflow, as MotionEvent user inputs are provided incrementally. This is a more generalized version of InProgressStrokesView for specialized developer needs for custom shapes. For normal usage, InProgressStrokesView is recommended. For a Jetpack Compose equivalent which also provides a default input handler, see androidx.ink.authoring.compose.InProgressShapes instead.
Summary
Public constructors |
|---|
<ShapeSpecT extends Object, InProgressShapeT extends InProgressShape<@NonNull ShapeSpecT, @NonNull CompletedShapeT>, CompletedShapeT extends Object> InProgressShapesView( |
Public methods |
|
|---|---|
final void |
addCompletedShapesListener(Add a listener to be notified when shapes are finished. |
final boolean |
addToShape(Add |
final void |
addToShape(Add input data from a |
final void |
addToShape(Add input data, from a particular pointer within a |
final boolean |
cancelShape(@NonNull MotionEvent event, int pointerId)Cancel the corresponding in-progress shape with |
final void |
cancelShape(@NonNull InProgressStrokeId shapeId, MotionEvent event)Cancel the building of a shape. |
final void |
Cancel all in-progress shapes. |
final void |
Removes all listeners that had previously been added with |
final void |
Eagerly initialize rather than waiting for the first shape to be drawn. |
final boolean |
finishShape(@NonNull MotionEvent event, int pointerId)Finish the corresponding in-progress shape with |
final void |
finishShape(Finish providing inputs for the shape represented by the given |
final void |
finishShape(Complete the building of a shape, with the last input data coming from a particular pointer of a |
final @NonNull Map<@NonNull InProgressStrokeId, @NonNull CompletedShapeT> |
Returns all the finished shapes that are still being rendered by this view, with map iteration order in the z-order that the shapes are being rendered, from back to front. |
final ShapeWorkflow<@NonNull ShapeSpecT, @NonNull InProgressShapeT, @NonNull CompletedShapeT> |
A |
final CountingIdlingResource |
Allows a test to easily wait until all in-progress shapes are completed and handed off. |
final Path |
Denote an area of this |
final @NonNull Matrix |
The transform matrix to convert |
final boolean |
Returns true if there are any in-progress shapes. |
final void |
@UiThreadStop this view from rendering the shapes with the given IDs. |
final void |
removeCompletedShapesListener(Removes a listener that had previously been added with |
final void |
setCustomShapeWorkflow(A |
final void |
setInProgressShapeCounter(Allows a test to easily wait until all in-progress shapes are completed and handed off. |
final void |
setMaskPath(Path maskPath)Denote an area of this |
final void |
setMotionEventToViewTransform(The transform matrix to convert |
final @NonNull InProgressStrokeId |
startShape(Start building a shape with the provided |
final @NonNull InProgressStrokeId |
startShape(Start building a shape using a particular pointer within a |
Protected methods |
|
|---|---|
void |
|
void |
Inherited methods |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Public constructors
InProgressShapesView
public <ShapeSpecT extends Object, InProgressShapeT extends InProgressShape<@NonNull ShapeSpecT, @NonNull CompletedShapeT>, CompletedShapeT extends Object> InProgressShapesView(
@NonNull Context context,
AttributeSet attrs,
@AttrRes int defStyleAttr
)
Public methods
addCompletedShapesListener
public final void addCompletedShapesListener(
@NonNull InProgressShapesCompletedListener<@NonNull CompletedShapeT> listener
)
Add a listener to be notified when shapes are finished. These shapes will continue to be rendered within this view until removeCompletedShapes is called. All of the shapes that have been delivered to listeners but have not yet been removed with removeCompletedShapes are available through getCompletedShapes.
addToShape
public final boolean addToShape(
@NonNull MotionEvent event,
int pointerId,
MotionEvent prediction
)
Add event data for pointerId to the corresponding in-progress shape, if present. The shape must have been started with an overload of startShape that accepts a MotionEvent.
| Parameters | |
|---|---|
@NonNull MotionEvent event |
The next |
int pointerId |
The index of the relevant pointer in the |
MotionEvent prediction |
An optional predicted |
| Returns | |
|---|---|
boolean |
Whether the pointer corresponds to an in-progress shape. |
addToShape
public final void addToShape(
@NonNull StrokeInputBatch inputs,
@NonNull InProgressStrokeId shapeId,
@NonNull StrokeInputBatch prediction
)
Add input data from a StrokeInputBatch to an existing shape. The shape must have been started with an overload of startShape that accepts a StrokeInput.
| Parameters | |
|---|---|
@NonNull StrokeInputBatch inputs |
The next |
@NonNull InProgressStrokeId shapeId |
The |
@NonNull StrokeInputBatch prediction |
Predicted |
addToShape
public final void addToShape(
@NonNull MotionEvent event,
int pointerId,
@NonNull InProgressStrokeId shapeId,
MotionEvent prediction
)
Add input data, from a particular pointer within a MotionEvent, to an existing shape. The shape must have been started with an overload of startShape that accepts a MotionEvent.
| Parameters | |
|---|---|
@NonNull MotionEvent event |
The next |
int pointerId |
The identifier of the pointer within |
@NonNull InProgressStrokeId shapeId |
The |
MotionEvent prediction |
Predicted |
cancelShape
public final boolean cancelShape(@NonNull MotionEvent event, int pointerId)
Cancel the corresponding in-progress shape with event data for pointerId, if present. The shape must have been started with an overload of startShape that accepts a MotionEvent.
| Parameters | |
|---|---|
@NonNull MotionEvent event |
The |
int pointerId |
the id of the relevant pointer in the |
| Returns | |
|---|---|
boolean |
Whether the pointer corresponded to an in-progress shape. |
cancelShape
public final void cancelShape(@NonNull InProgressStrokeId shapeId, MotionEvent event)
Cancel the building of a shape. It will no longer be visible within this InProgressShapesView, and no CompletedShapeT object will come through InProgressShapesCompletedListener for the given shapeId.
This is typically done for one of three reasons:
-
A
MotionEventwithMotionEvent.getActionMaskedofMotionEvent.ACTION_CANCEL. This tends to be when an entire gesture has been canceled, for example when a parentViewusesandroid.view.ViewGroup.onInterceptTouchEventto intercept and handle the gesture itself. -
A
MotionEventwithMotionEvent.getFlagscontainingMotionEvent.FLAG_CANCELED. This tends to be when the system has detected an unintentional touch, such as from the user resting their palm on the screen while writing or drawing, after some events from that unintentional pointer have already been delivered. -
An app's business logic reinterprets a gesture previously used for inking as something else, and the earlier inking may be seen as unintentional. For example, an app that uses single-pointer gestures for inking and dual-pointer gestures for pan/zoom/rotate will start inking when the first pointer goes down, but when the second pointer goes down it may want to cancel the shape from the first pointer rather than leave the small ink marks on the screen.
Does nothing if a shape with the given shapeId is not in progress.
| Parameters | |
|---|---|
@NonNull InProgressStrokeId shapeId |
The |
MotionEvent event |
The |
cancelUnfinishedShapes
public final void cancelUnfinishedShapes()
Cancel all in-progress shapes.
clearCompletedShapesListeners
public final void clearCompletedShapesListeners()
Removes all listeners that had previously been added with addCompletedShapesListener.
eagerInit
public final void eagerInit()
Eagerly initialize rather than waiting for the first shape to be drawn. Since initialization can be somewhat heavyweight, doing this as soon as it's likely for the user to start drawing can prevent initialization from introducing latency to the first shape.
finishShape
public final boolean finishShape(@NonNull MotionEvent event, int pointerId)
Finish the corresponding in-progress shape with event data for pointerId, if present. The shape must have been started with an overload of startShape that accepts a MotionEvent. The resulting CompletedShapeT will be passed to InProgressShapesCompletedListener (registered with addCompletedShapesListener) shortly after all currently in-progress shapes are finished.
| Parameters | |
|---|---|
@NonNull MotionEvent event |
the last |
int pointerId |
the id of the relevant pointer in the |
| Returns | |
|---|---|
boolean |
Whether the pointer corresponded to an in-progress shape. |
finishShape
public final void finishShape(
@NonNull StrokeInput input,
@NonNull InProgressStrokeId shapeId
)
Finish providing inputs for the shape represented by the given shapeId, with the last input data coming from a StrokeInput. The shape must have been started with an overload of startShape that accepts a StrokeInput. The resulting CompletedShapeT will be passed to InProgressShapesCompletedListener (registered with addCompletedShapesListener) shortly after all currently in-progress shapes are finished.
| Parameters | |
|---|---|
@NonNull StrokeInput input |
The last |
@NonNull InProgressStrokeId shapeId |
The |
finishShape
public final void finishShape(
@NonNull MotionEvent event,
int pointerId,
@NonNull InProgressStrokeId shapeId
)
Complete the building of a shape, with the last input data coming from a particular pointer of a MotionEvent. The shape must have been started with an overload of startShape that accepts a MotionEvent.
The resulting CompletedShapeT will be passed to InProgressShapesCompletedListener (registered with addCompletedShapesListener) shortly after all currently in-progress shapes are finished.
Does nothing if a shape with the given shapeId is not in progress.
| Parameters | |
|---|---|
@NonNull MotionEvent event |
The last |
int pointerId |
The identifier of the pointer within |
@NonNull InProgressStrokeId shapeId |
The |
getCompletedShapes
public final @NonNull Map<@NonNull InProgressStrokeId, @NonNull CompletedShapeT> getCompletedShapes()
Returns all the finished shapes that are still being rendered by this view, with map iteration order in the z-order that the shapes are being rendered, from back to front. This is the same order that shapes were started with startShape. The IDs of these shapes should be passed to removeCompletedShapes when they are handed off to another view.
getCustomShapeWorkflow
public final ShapeWorkflow<@NonNull ShapeSpecT, @NonNull InProgressShapeT, @NonNull CompletedShapeT> getCustomShapeWorkflow()
A ShapeWorkflow to be used as an alternative to the standard Ink behavior provided by InProgressStrokesView. It must be set before the first call to startShape or eagerInit.
getInProgressShapeCounter
public final CountingIdlingResource getInProgressShapeCounter()
Allows a test to easily wait until all in-progress shapes are completed and handed off. There is no reason to set this in non-test code.
getMaskPath
public final Path getMaskPath()
Denote an area of this InProgressShapesView where no ink should be visible. A value of null indicates that shapes will be visible anywhere they are drawn. This is useful for UI elements that float on top of (in Z order) the drawing surface - without this, a user would be able to draw in-progress ("wet") shapes on top of those UI elements, but then when the shape is finished, it will appear as a dry shape underneath of the UI element. If this mask is set to the shape and position of the floating UI element, then the ink will never be rendered in that area, making it appear as if it's being drawn underneath the UI element.
This technique is most convincing when the UI element is opaque. Often there are parts of the UI element that are translucent, such as drop shadows, or anti-aliasing along the edges. The result will look a little different between wet and dry shapes for those cases, but it can be a worthwhile tradeoff compared to the alternative of drawing wet shapes on top of that UI element.
Note that this parameter does not affect the contents of the shapes at all, nor how they appear when drawn in a separate composable after InProgressShapesCompletedListener.onShapesCompleted is called - just how the shapes appear when they are still in progress in this view.
getMotionEventToViewTransform
public final @NonNull Matrix getMotionEventToViewTransform()
The transform matrix to convert MotionEvent coordinates, as passed to startShape, addToShape, and finishShape, into coordinates of this InProgressShapesView for rendering. Defaults to the identity matrix, for the recommended case where InProgressShapesView exactly overlays the android.view.View that has the touch listener from which MotionEvent instances are being forwarded.
hasUnfinishedShapes
public final boolean hasUnfinishedShapes()
Returns true if there are any in-progress shapes.
removeCompletedShapes
@UiThread
public final void removeCompletedShapes(@NonNull Set<@NonNull InProgressStrokeId> strokeIds)
Stop this view from rendering the shapes with the given IDs.
This should be called in the same UI thread run loop (HWUI frame) as when the shapes start being rendered elsewhere in the view hierarchy. This means they are saved in a location where they will be picked up in a view's next call to onDraw, and that view's invalidate method has been called. If these two operations are not done within the same UI thread run loop (usually side by side - see example below), then there will be brief rendering errors - either a visual gap where the shape is not drawn during a frame, or a double draw where the shape is drawn twice and translucent shapes appear more opaque than they should.
removeCompletedShapesListener
public final void removeCompletedShapesListener(
@NonNull InProgressShapesCompletedListener<@NonNull CompletedShapeT> listener
)
Removes a listener that had previously been added with addCompletedShapesListener.
setCustomShapeWorkflow
public final void setCustomShapeWorkflow(
ShapeWorkflow<@NonNull ShapeSpecT, @NonNull InProgressShapeT, @NonNull CompletedShapeT> customShapeWorkflow
)
A ShapeWorkflow to be used as an alternative to the standard Ink behavior provided by InProgressStrokesView. It must be set before the first call to startShape or eagerInit.
setInProgressShapeCounter
public final void setInProgressShapeCounter(
@VisibleForTesting CountingIdlingResource inProgressShapeCounter
)
Allows a test to easily wait until all in-progress shapes are completed and handed off. There is no reason to set this in non-test code.
setMaskPath
public final void setMaskPath(Path maskPath)
Denote an area of this InProgressShapesView where no ink should be visible. A value of null indicates that shapes will be visible anywhere they are drawn. This is useful for UI elements that float on top of (in Z order) the drawing surface - without this, a user would be able to draw in-progress ("wet") shapes on top of those UI elements, but then when the shape is finished, it will appear as a dry shape underneath of the UI element. If this mask is set to the shape and position of the floating UI element, then the ink will never be rendered in that area, making it appear as if it's being drawn underneath the UI element.
This technique is most convincing when the UI element is opaque. Often there are parts of the UI element that are translucent, such as drop shadows, or anti-aliasing along the edges. The result will look a little different between wet and dry shapes for those cases, but it can be a worthwhile tradeoff compared to the alternative of drawing wet shapes on top of that UI element.
Note that this parameter does not affect the contents of the shapes at all, nor how they appear when drawn in a separate composable after InProgressShapesCompletedListener.onShapesCompleted is called - just how the shapes appear when they are still in progress in this view.
setMotionEventToViewTransform
public final void setMotionEventToViewTransform(
@NonNull Matrix motionEventToViewTransform
)
The transform matrix to convert MotionEvent coordinates, as passed to startShape, addToShape, and finishShape, into coordinates of this InProgressShapesView for rendering. Defaults to the identity matrix, for the recommended case where InProgressShapesView exactly overlays the android.view.View that has the touch listener from which MotionEvent instances are being forwarded.
startShape
public final @NonNull InProgressStrokeId startShape(
@NonNull StrokeInput input,
@NonNull ShapeSpecT shapeSpec,
@NonNull Matrix shapeToViewTransform
)
Start building a shape with the provided input. This would typically be followed by many calls to addToShape, and the sequence would end with a call to either finishShape or cancelShape.
In most circumstances, the startShape overload that accepts a MotionEvent is more convenient. However, this overload using a StrokeInput is available for cases where the input data may not come directly from a MotionEvent, such as receiving events over a network connection. Using this function to start a shape can only be followed by the StrokeInput variants of addToShape and finishShape for the same shape.
If there is a way to request unbuffered dispatch from the source of the input data used here, equivalent to View.requestUnbufferedDispatch for unbuffered MotionEvent data, then be sure to request it for optimal performance.
| Parameters | |
|---|---|
@NonNull StrokeInput input |
The |
@NonNull ShapeSpecT shapeSpec |
Specification for the shape being started. |
@NonNull Matrix shapeToViewTransform |
The |
| Returns | |
|---|---|
@NonNull InProgressStrokeId |
The |
startShape
public final @NonNull InProgressStrokeId startShape(
@NonNull MotionEvent event,
int pointerId,
@NonNull ShapeSpecT shapeSpec,
@NonNull Matrix motionEventToWorldTransform,
@NonNull Matrix shapeToWorldTransform
)
Start building a shape using a particular pointer within a MotionEvent. This would typically be followed by many calls to addToShape, and the sequence would end with a call to either finishShape or cancelShape.
In most circumstances, prefer to use this function over startShape that accepts a StrokeInput. Using this function to start a shape must only be followed by the MotionEvent variants of addToShape and finishShape for the same shape.
For optimum performance, it is strongly recommended to call View.requestUnbufferedDispatch using event and the View that generated event alongside calling this function. When requested this way, unbuffered dispatch mode will automatically end when the gesture is complete.
| Parameters | |
|---|---|
@NonNull MotionEvent event |
The first |
int pointerId |
The identifier of the pointer within |
@NonNull ShapeSpecT shapeSpec |
Specification for the shape being started. |
@NonNull Matrix motionEventToWorldTransform |
The matrix that transforms |
@NonNull Matrix shapeToWorldTransform |
Allows an object-specific (shape-specific) coordinate space to be defined in relation to the caller's "world" coordinate space. This defaults to the identity matrix, which is typical for many use cases at the time of shape construction. In typical use cases, shape coordinates and world coordinates may start to differ from one another after shape creation as a particular shape is manipulated within the world, e.g. it may be moved, scaled, or rotated relative to other content within an app's document. This matrix must be invertible. |
| Returns | |
|---|---|
@NonNull InProgressStrokeId |
The |
| Throws | |
|---|---|
kotlin.IllegalArgumentException |
if |