GestureScope

Added in 1.0.0
Deprecated in 1.1.0

The receiver scope for injecting gestures on the SemanticsNode identified by the corresponding SemanticsNodeInteraction. Gestures can be injected by calling methods defined on GestureScope, such as click or swipe. The SemanticsNodeInteraction can be found by one of the finder methods such as onNode.

The functions in GestureScope can roughly be divided into two groups: full gestures and individual touch events. The individual touch events are: down, move and friends, up, cancel and advanceEventTime. Full gestures are all the other functions, like click, doubleClick, swipe, etc. See the documentation of down for more information about individual events. If you execute a full gesture while in the middle of another gesture, an IllegalStateException or IllegalArgumentException can be thrown when the pointerId is unintentionally used for both gestures. If you want to perform e.g. a click during a partially performed gesture, make sure they use different pointer ids.

Note that all events generated by the gesture methods are batched together and sent as a whole after performGesture has executed its code block.

Next to the functions, GestureScope also exposes several properties that allow you to get coordinates within a node, like the top left corner, its center, or some percentage of the size (percentOffset).

Example of performing a click:

import androidx.compose.ui.test.click
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performGesture

composeTestRule.onNodeWithTag("myComponent").performGesture { click() }

Example of performing a swipe up:

import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performGesture
import androidx.compose.ui.test.swipeUp

composeTestRule.onNodeWithTag("myComponent").performGesture { swipeUp() }

Example of performing an L-shaped gesture:

import androidx.compose.ui.test.center
import androidx.compose.ui.test.centerLeft
import androidx.compose.ui.test.down
import androidx.compose.ui.test.moveTo
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.percentOffset
import androidx.compose.ui.test.performGesture
import androidx.compose.ui.test.topLeft
import androidx.compose.ui.test.up

composeTestRule.onNodeWithTag("myComponent").performGesture {
    down(topLeft)
    moveTo(topLeft + percentOffset(0f, .1f))
    moveTo(topLeft + percentOffset(0f, .2f))
    moveTo(topLeft + percentOffset(0f, .3f))
    moveTo(topLeft + percentOffset(0f, .4f))
    moveTo(centerLeft)
    moveTo(centerLeft + percentOffset(.1f, 0f))
    moveTo(centerLeft + percentOffset(.2f, 0f))
    moveTo(centerLeft + percentOffset(.3f, 0f))
    moveTo(centerLeft + percentOffset(.4f, 0f))
    moveTo(center)
    up()
}

Summary

Public constructors

GestureScope(node: SemanticsNode, testContext: TestContext)
Cmn

Public properties

IntSize

Returns the size of the visible part of the node we're interacting with.

Cmn

Extension functions

Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.doubleClick(position: Offset, delayMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.down(pointerId: Int, position: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.longClick(position: Offset, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.moveBy(pointerId: Int, delta: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.movePointerBy(pointerId: Int, delta: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.movePointerTo(pointerId: Int, position: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.moveTo(pointerId: Int, position: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.pinch(
    start0: Offset,
    end0: Offset,
    start1: Offset,
    end1: Offset,
    durationMillis: Long
)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.swipe(start: Offset, end: Offset, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
@ExperimentalTestApi
GestureScope.swipeDown(startY: Float, endY: Float, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
@ExperimentalTestApi
GestureScope.swipeLeft(startX: Float, endX: Float, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
@ExperimentalTestApi
GestureScope.swipeRight(startX: Float, endX: Float, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
@ExperimentalTestApi
GestureScope.swipeUp(startY: Float, endY: Float, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.swipeWithVelocity(
    start: Offset,
    end: Offset,
    endVelocity: Float,
    durationMillis: Long
)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.up(pointerId: Int)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn

Extension properties

Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Int

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Int

This property is deprecated. Replaced by TouchInjectionScope.

Cmn

Public constructors

GestureScope

GestureScope(node: SemanticsNode, testContext: TestContext)

Public properties

visibleSize

val visibleSizeIntSize

Returns the size of the visible part of the node we're interacting with. This is contrary to SemanticsNode.size, which returns the unclipped size of the node.

Extension functions

advanceEventTime

@ExperimentalTestApi
fun GestureScope.advanceEventTime(durationMillis: Long): Unit

Adds the given durationMillis to the current event time, delaying the next event by that time. Only valid when a gesture has already been started, or when a finished gesture is resumed.

fun GestureScope.cancel(): Unit

Sends a cancel event to cancel the current gesture. The cancel event contains the current position of all active pointers.

fun GestureScope.click(position: Offset = center): Unit

Performs a click gesture at the given position on the associated node, or in the center if the position is omitted. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default position is the center of the node.

Parameters
position: Offset = center

The position where to click, in the node's local coordinate system. If omitted, the center position will be used.

doubleClick

fun GestureScope.doubleClick(
    position: Offset = center,
    delayMillis: Long = doubleClickDelayMillis
): Unit

Performs a double click gesture at the given position on the associated node, or in the center if the position is omitted. By default, the delayMillis between the first and the second click is 145 milliseconds (empirically established). The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Parameters
position: Offset = center

The position of the double click, in the node's local coordinate system. If omitted, the center position will be used.

delayMillis: Long = doubleClickDelayMillis

The time between the up event of the first click and the down event of the second click

fun GestureScope.down(position: Offset): Unit

Sends a down event for the default pointer at position on the associated node. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default pointer has pointerId = 0.

If no pointers are down yet, this will start a new gesture. If a gesture is already in progress, this event is sent with at the same timestamp as the last event. If the default pointer is already down, an IllegalArgumentException will be thrown.

Parameters
position: Offset

The position of the down event, in the node's local coordinate system

fun GestureScope.down(pointerId: Int, position: Offset): Unit

Sends a down event for the pointer with the given pointerId at position on the associated node. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

If no pointers are down yet, this will start a new gesture. If a gesture is already in progress, this event is sent with at the same timestamp as the last event. If the given pointer is already down, an IllegalArgumentException will be thrown.

Subsequent events for this or other gestures can be spread out over both this and future invocations of performGesture. An entire gesture starts with a down event, followed by several down, move or up events, and ends with an up or a cancel event. Movement can be expressed with moveTo and moveBy to move a single pointer at a time, or movePointerTo and movePointerBy to move multiple pointers at a time. The movePointer[To|By] methods do not send the move event directly, use move to send the move event. Some other methods can send a move event as well. All events, regardless the method used, will always contain the current position of all pointers.

Down and up events are sent at the same time as the previous event, but will send an extra move event just before the down or up event if movePointerTo or movePointerBy has been called and no move event has been sent yet. This does not happen for cancel events, but the cancel event will contain the up to date position of all pointers. Move and cancel events will advance the event time by 16 milliseconds.

Because gestures don't have to be defined all in the same performGesture block, keep in mind that while the gesture is not complete, all code you execute in between blocks that progress the gesture, will be executed while imaginary fingers are actively touching the screen.

In the context of testing, it is not necessary to complete a gesture with an up or cancel event, if the test ends before it expects the finger to be lifted from the screen.

Parameters
pointerId: Int

The id of the pointer, can be any number not yet in use by another pointer

position: Offset

The position of the down event, in the node's local coordinate system

longClick

fun GestureScope.longClick(
    position: Offset = center,
    durationMillis: Long = LongPressTimeoutMillis + 100
): Unit

Performs a long click gesture at the given position on the associated node, or in the center if the position is omitted. By default, the durationMillis of the press is LongPressTimeoutMillis + 100 milliseconds. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Parameters
position: Offset = center

The position of the long click, in the node's local coordinate system. If omitted, the center position will be used.

durationMillis: Long = LongPressTimeoutMillis + 100

The time between the down and the up event

fun GestureScope.move(): Unit

Sends a move event without updating any of the pointer positions. This can be useful when batching movement of multiple pointers together, which can be done with movePointerTo and movePointerBy.

fun GestureScope.moveBy(delta: Offset): Unit

Sends a move event on the associated node, with the position of the default pointer moved by the given delta. The default pointer has pointerId = 0.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
delta: Offset

The position for this move event, relative to the last sent position of the pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's last x-position, and subtract 10.px from the pointer's last y-position.

fun GestureScope.moveBy(pointerId: Int, delta: Offset): Unit

Sends a move event on the associated node, with the position of the pointer with the given pointerId moved by the given delta.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
pointerId: Int

The id of the pointer to move, as supplied in down

delta: Offset

The position for this move event, relative to the last sent position of the pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's last x-position, and subtract 10.px from the pointer's last y-position.

movePointerBy

fun GestureScope.movePointerBy(pointerId: Int, delta: Offset): Unit

Moves the position of the pointer with the given pointerId by the given delta, but does not send a move event. The move event can be sent with move.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
pointerId: Int

The id of the pointer to move, as supplied in down

delta: Offset

The position for this move event, relative to the last sent position of the pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's last x-position, and subtract 10.px from the pointer's last y-position.

movePointerTo

fun GestureScope.movePointerTo(pointerId: Int, position: Offset): Unit

Updates the position of the pointer with the given pointerId to the given position, but does not send a move event. The move event can be sent with move. The position is in the node's local coordinate system, where (0.px, 0.px) is the top left corner of the node.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
pointerId: Int

The id of the pointer to move, as supplied in down

position: Offset

The new position of the pointer, in the node's local coordinate system

fun GestureScope.moveTo(position: Offset): Unit

Sends a move event on the associated node, with the position of the default pointer updated to position. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default pointer has pointerId = 0.

If the default pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
position: Offset

The new position of the pointer, in the node's local coordinate system

fun GestureScope.moveTo(pointerId: Int, position: Offset): Unit

Sends a move event on the associated node, with the position of the pointer with the given pointerId updated to position. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
pointerId: Int

The id of the pointer to move, as supplied in down

position: Offset

The new position of the pointer, in the node's local coordinate system

percentOffset

fun GestureScope.percentOffset(x: Float = 0.0f, y: Float = 0.0f): Offset

Creates an Offset relative to the size of the node we're interacting with. x and y are fractions of the width and height, between -1 and 1. Note that percentOffset(1f, 1f) != bottomRight, see right and bottom.

For example: percentOffset(.5f, .5f) is the same as the center; centerLeft + percentOffset(.1f, 0f) is a point 10% inward from the middle of the left edge; and bottomRight - percentOffset(.2f, .1f) is a point 20% to the left and 10% to the top of the bottom right corner.

fun GestureScope.pinch(
    start0: Offset,
    end0: Offset,
    start1: Offset,
    end1: Offset,
    durationMillis: Long = 400
): Unit

Performs a pinch gesture on the associated node.

For each pair of start and end Offsets, the motion events are linearly interpolated. The coordinates are in the node's local coordinate system where (0, 0) is the top left corner of the node. The default duration is 400 milliseconds.

Parameters
start0: Offset

The start position of the first gesture in the node's local coordinate system

end0: Offset

The end position of the first gesture in the node's local coordinate system

start1: Offset

The start position of the second gesture in the node's local coordinate system

end1: Offset

The end position of the second gesture in the node's local coordinate system

durationMillis: Long = 400

the duration of the gesture

fun GestureScope.swipe(start: Offset, end: Offset, durationMillis: Long = 200): Unit

Performs the swipe gesture on the associated node. The motion events are linearly interpolated between start and end. The coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default duration is 200 milliseconds.

Parameters
start: Offset

The start position of the gesture, in the node's local coordinate system

end: Offset

The end position of the gesture, in the node's local coordinate system

durationMillis: Long = 200

The duration of the gesture

swipeDown

fun GestureScope.swipeDown(): Unit

Performs a swipe down gesture along the centerX of the associated node. The gesture starts slightly below the top of the node and ends at the bottom.

swipeDown

@ExperimentalTestApi
fun GestureScope.swipeDown(
    startY: Float = topFuzzed,
    endY: Float = bottom,
    durationMillis: Long = 200
): Unit

Performs a swipe down gesture along the centerX of the associated node, from startY till endY, taking durationMillis milliseconds.

Parameters
startY: Float = topFuzzed

The y-coordinate of the start of the swipe. Must be less than or equal to the endY. By default slightly below the top of the node.

endY: Float = bottom

The y-coordinate of the end of the swipe. Must be greater than or equal to the startY. By default the bottom of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeLeft

fun GestureScope.swipeLeft(): Unit

Performs a swipe left gesture along the centerY of the associated node. The gesture starts slightly left of the right side of the node and ends at the left side.

swipeLeft

@ExperimentalTestApi
fun GestureScope.swipeLeft(
    startX: Float = rightFuzzed,
    endX: Float = left,
    durationMillis: Long = 200
): Unit

Performs a swipe left gesture along the centerY of the associated node, from startX till endX, taking durationMillis milliseconds.

Parameters
startX: Float = rightFuzzed

The x-coordinate of the start of the swipe. Must be greater than or equal to the endX. By default slightly left of the right of the node.

endX: Float = left

The x-coordinate of the end of the swipe. Must be less than or equal to the startX. By default the left of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeRight

fun GestureScope.swipeRight(): Unit

Performs a swipe right gesture along the centerY of the associated node. The gesture starts slightly right of the left side of the node and ends at the right side.

swipeRight

@ExperimentalTestApi
fun GestureScope.swipeRight(
    startX: Float = leftFuzzed,
    endX: Float = right,
    durationMillis: Long = 200
): Unit

Performs a swipe right gesture along the centerY of the associated node, from startX till endX, taking durationMillis milliseconds.

Parameters
startX: Float = leftFuzzed

The x-coordinate of the start of the swipe. Must be less than or equal to the endX. By default slightly right of the left of the node.

endX: Float = right

The x-coordinate of the end of the swipe. Must be greater than or equal to the startX. By default the right of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

fun GestureScope.swipeUp(): Unit

Performs a swipe up gesture along the centerX of the associated node. The gesture starts slightly above the bottom of the node and ends at the top.

@ExperimentalTestApi
fun GestureScope.swipeUp(
    startY: Float = bottomFuzzed,
    endY: Float = top,
    durationMillis: Long = 200
): Unit

Performs a swipe up gesture along the centerX of the associated node, from startY till endY, taking durationMillis milliseconds.

Parameters
startY: Float = bottomFuzzed

The y-coordinate of the start of the swipe. Must be greater than or equal to the endY. By default slightly above the bottom of the node.

endY: Float = top

The y-coordinate of the end of the swipe. Must be less than or equal to the startY. By default the top of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeWithVelocity

fun GestureScope.swipeWithVelocity(
    start: Offset,
    end: Offset,
    endVelocity: Float,
    durationMillis: Long = 200
): Unit

Performs the swipe gesture on the associated node, such that the velocity when the gesture is finished is roughly equal to endVelocity. The MotionEvents are linearly interpolated between start and end. The coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default duration is 200 milliseconds.

Note that due to imprecisions, no guarantees can be made on the precision of the actual velocity at the end of the gesture, but generally it is within 0.1% of the desired velocity.

Parameters
start: Offset

The start position of the gesture, in the node's local coordinate system

end: Offset

The end position of the gesture, in the node's local coordinate system

endVelocity: Float

The velocity of the gesture at the moment it ends. Must be positive.

durationMillis: Long = 200

The duration of the gesture in milliseconds. Must be long enough that at least 3 input events are generated, which happens with a duration of 25ms or more.

fun GestureScope.up(pointerId: Int = 0): Unit

Sends an up event for the pointer with the given pointerId, or the default pointer if pointerId is omitted, on the associated node. If any pointers have been moved with movePointerTo or movePointerBy and no move event has been sent yet, a move event will be sent right before the up event.

Parameters
pointerId: Int = 0

The id of the pointer to lift up, as supplied in down

Extension properties

bottom

val GestureScope.bottomFloat

Returns the y-coordinate for the bottom of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that, unless height == 0, bottom != height. In particular, bottom == height - 1f, because pixels are 0-based. If height == 0, bottom == 0 too.

bottomCenter

val GestureScope.bottomCenterOffset

Returns the center of the bottom edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that bottomCenter.y != height, see bottom.

bottomLeft

val GestureScope.bottomLeftOffset

Returns the bottom left corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that bottomLeft.y != height, see bottom.

bottomRight

val GestureScope.bottomRightOffset

Returns the bottom right corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that bottomRight.x != width and bottomRight.y != height, see right and bottom.

center

val GestureScope.centerOffset

Returns the center of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

centerLeft

val GestureScope.centerLeftOffset

Returns the center of the left edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

centerRight

val GestureScope.centerRightOffset

Returns the center of the right edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that centerRight.x != width, see right.

centerX

val GestureScope.centerXFloat

Returns the x-coordinate for the center of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

centerY

val GestureScope.centerYFloat

Returns the y-coordinate for the center of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

height

val GestureScope.heightInt

Shorthand for size.height

left

val GestureScope.leftFloat

Returns the x-coordinate for the left edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

right

val GestureScope.rightFloat

Returns the x-coordinate for the right edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that, unless width == 0, right != width. In particular, right == width - 1f, because pixels are 0-based. If width == 0, right == 0 too.

top

val GestureScope.topFloat

Returns the y-coordinate for the bottom of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

topCenter

val GestureScope.topCenterOffset

Returns the center of the top edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

topLeft

val GestureScope.topLeftOffset

Returns the top left corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

topRight

val GestureScope.topRightOffset

Returns the top right corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that topRight.x != width, see right.

width

val GestureScope.widthInt

Shorthand for size.width