androidx.compose.ui.input.pointer

Interfaces

AwaitPointerEventScope

Receiver scope for awaiting pointer events in a call to PointerInputScope.awaitPointerEventScope.

Cmn
PointerIcon

Represents a pointer icon to use in Modifier.pointerHoverIcon

Cmn
PointerInputEventHandler
Cmn
PointerInputModifier

A Modifier.Element that can interact with pointer input.

Cmn
PointerInputScope

Receiver scope for Modifier.pointerInput that permits handling pointer input.

Cmn
SuspendingPointerInputModifierNode

Extends PointerInputModifierNode with a handler to execute asynchronously when an event occurs and a function to reset that handler (cancels the existing coroutine and essentially resets the handler's execution).

Cmn

Classes

ConsumedData

This class is deprecated. Use PointerInputChange.isConsumed and PointerInputChange.consume() instead

Cmn
HistoricalChange

Data structure for "historical" pointer moves.

Cmn
NativePointerButtons
Cmn
NativePointerKeyboardModifiers
Cmn
PointerButtons

Contains the state of pointer buttons (e.g. mouse and stylus buttons).

Cmn
PointerEvent

Describes a pointer input change event that has occurred at a particular point in time.

Cmn
android
PointerEventType

Indicates the primary reason that the PointerEvent was sent.

Cmn
PointerId

An ID for a given pointer.

Cmn
PointerInputChange

Describes a change that has occurred for a particular pointer, as well as how much of the change has been consumed (meaning, used by a node in the UI).

Cmn
PointerInputFilter

A PointerInputFilter represents a single entity that receives PointerInputChanges), interprets them, and consumes the aspects of the changes that it is react to such that other PointerInputFilters don't also react to them.

Cmn
PointerKeyboardModifiers

Contains the state of modifier keys, such as Shift, Control, and Alt, as well as the state of the lock keys, such as Caps Lock and Num Lock.

Cmn
PointerType

The device type that produces a PointerInputChange, such as a mouse or stylus.

Cmn
RequestDisallowInterceptTouchEvent

Function that can be passed to pointerInteropFilter and then later invoked which provides an analog to ViewParent.requestDisallowInterceptTouchEvent.

android

Exceptions

PointerEventTimeoutCancellationException

An exception thrown from AwaitPointerEventScope.withTimeout when the execution time of the coroutine is too long.

Cmn
android

Enums

PointerEventPass

The enumeration of passes where PointerInputChange traverses up and down the UI tree.

Cmn

Top-level functions summary

PointerIcon
PointerIcon(pointerIcon: PointerIcon)

Creates PointerIcon from android.view.PointerIcon

android
PointerIcon
PointerIcon(pointerIconType: Int)

Creates PointerIcon from pointer icon type (see android.view.PointerIcon.getSystemIcon

android
SuspendingPointerInputModifierNode

Supports suspending pointer event handling.

Cmn

Extension functions summary

Boolean

This function is deprecated. Partial consumption has been deprecated.

Cmn
Boolean

True if this PointerInputChange represents a pointer coming in contact with the screen and that change has not been consumed.

Cmn
Boolean

True if this PointerInputChange represents a pointer coming in contact with the screen, whether or not that change has been consumed.

Cmn
Boolean

True if this PointerInputChange represents a pointer breaking contact with the screen and that change has not been consumed.

Cmn
Boolean

True if this PointerInputChange represents a pointer breaking contact with the screen, whether or not that change has been consumed.

Cmn
Unit

This function is deprecated. Use consume() instead

Cmn
Unit

This function is deprecated. Partial consumption has been deprecated.

Cmn
Unit

This function is deprecated. Partial consumption has been deprecated.

Cmn
Int

Returns the index of first button pressed as used in isPressed or -1 if no button is pressed.

Cmn
android
Int

Returns the index of last button pressed as used in isPressed or -1 if no button is pressed.

Cmn
android
Boolean

This function is deprecated. Use isOutOfBounds() that supports minimum touch target

Cmn
Boolean
PointerInputChange.isOutOfBounds(
    size: IntSize,
    extendedTouchPadding: Size
)

Returns true if the pointer has moved outside of the pointer region.

Cmn
Boolean

Returns true when the button at buttonIndex is pressed and false when it isn't pressed.

Cmn
android
Modifier
Modifier.motionEventSpy(watcher: (motionEvent: MotionEvent) -> Unit)

Calls watcher with each MotionEvent that the layout area or any child pointerInput receives.

android
Modifier
Modifier.pointerHoverIcon(
    icon: PointerIcon,
    overrideDescendants: Boolean
)

Modifier that lets a developer define a pointer icon to display when the cursor is hovered over the element.

Cmn
Modifier

This function is deprecated. Modifier.pointerInput must provide one or more 'key' parameters that define the identity of the modifier and determine when its previous input processing coroutine should be cancelled and a new effect launched for the new key.

Cmn
Modifier

Create a modifier for processing pointer input within the region of the modified element.

Cmn
Modifier

Create a modifier for processing pointer input within the region of the modified element.

Cmn
Modifier
Modifier.pointerInput(
    key1: Any?,
    key2: Any?,
    block: PointerInputEventHandler
)

Create a modifier for processing pointer input within the region of the modified element.

Cmn
Modifier
Modifier.pointerInteropFilter(
    requestDisallowInterceptTouchEvent: RequestDisallowInterceptTouchEvent?,
    onTouchEvent: (MotionEvent) -> Boolean
)

A special PointerInputModifier that provides access to the underlying MotionEvents originally dispatched to Compose.

android
Offset

The distance that the pointer has moved on the screen minus any distance that has been consumed.

Cmn
Boolean

This function is deprecated. Partial consumption has been deprecated.

Cmn
Offset

The distance that the pointer has moved on the screen, ignoring the fact that it might have been consumed.

Cmn
Boolean

True if this PointerInputChange represents a pointer moving on the screen and some of that movement has not been consumed.

Cmn
Boolean

True if this PointerInputChange represents a pointer moving on the screen ignoring how much of that movement may have been consumed.

Cmn

Extension properties summary

Boolean

Returns true if any button is pressed or false if all buttons are released.

Cmn
android
Boolean

true when the AltGraph key is pressed.

Cmn
android
Boolean

true when the Alt key is pressed.

Cmn
android
Boolean

true when the back button (mouse back button) is pressed or false when it isn't pressed or there is no mouse button assigned to "back."

Cmn
android
Boolean

true when the keyboard's Caps Lock is on.

Cmn
android
Boolean

true when the Control key is pressed.

Cmn
android
Boolean

true when the forward button (mouse forward button) is pressed or false when it isn't pressed or there is no button assigned to "forward."

Cmn
android
Boolean

true when the Function key is pressed.

Cmn
android
Boolean

true when the Meta key is pressed.

Cmn
android
Boolean

true when the keyboard's Num Lock is on.

Cmn
android
Boolean

true when the primary button (left mouse button) is pressed or false when it isn't pressed.

Cmn
android
Boolean

true when the keyboard's Scroll Lock is on.

Cmn
android
Boolean

true when the secondary button (right mouse button) is pressed or false when it isn't pressed.

Cmn
android
Boolean

true when the Shift key is pressed.

Cmn
android
Boolean

true when the Sym key is pressed.

Cmn
android
Boolean

true when the tertiary button (middle mouse button) is pressed or false when it isn't pressed.

Cmn
android

Top-level functions

PointerIcon

fun PointerIcon(pointerIcon: PointerIcon): PointerIcon

Creates PointerIcon from android.view.PointerIcon

PointerIcon

fun PointerIcon(pointerIconType: Int): PointerIcon

Creates PointerIcon from pointer icon type (see android.view.PointerIcon.getSystemIcon

SuspendingPointerInputModifierNode

fun SuspendingPointerInputModifierNode(
    pointerInputEventHandler: PointerInputEventHandler
): SuspendingPointerInputModifierNode

Supports suspending pointer event handling. This is used by pointerInput, so in most cases you should just use pointerInput for suspending pointer input. Creating a SuspendingPointerInputModifierNode should only be needed when you want to delegate to suspending pointer input as part of the implementation of a complex Modifier.Node.

Extension functions

anyChangeConsumed

fun PointerInputChange.anyChangeConsumed(): Boolean

True if any aspect of this PointerInputChange has been consumed.

changedToDown

fun PointerInputChange.changedToDown(): Boolean

True if this PointerInputChange represents a pointer coming in contact with the screen and that change has not been consumed.

changedToDownIgnoreConsumed

fun PointerInputChange.changedToDownIgnoreConsumed(): Boolean

True if this PointerInputChange represents a pointer coming in contact with the screen, whether or not that change has been consumed.

changedToUp

fun PointerInputChange.changedToUp(): Boolean

True if this PointerInputChange represents a pointer breaking contact with the screen and that change has not been consumed.

changedToUpIgnoreConsumed

fun PointerInputChange.changedToUpIgnoreConsumed(): Boolean

True if this PointerInputChange represents a pointer breaking contact with the screen, whether or not that change has been consumed.

consumeAllChanges

fun PointerInputChange.consumeAllChanges(): Unit

Consumes all changes associated with the PointerInputChange

consumeDownChange

fun PointerInputChange.consumeDownChange(): Unit

Consume the up or down change of this PointerInputChange if there is an up or down change to consume.

consumePositionChange

fun PointerInputChange.consumePositionChange(): Unit

Consume position change if there is any

indexOfFirstPressed

fun PointerButtons.indexOfFirstPressed(): Int

Returns the index of first button pressed as used in isPressed or -1 if no button is pressed.

indexOfLastPressed

fun PointerButtons.indexOfLastPressed(): Int

Returns the index of last button pressed as used in isPressed or -1 if no button is pressed.

isOutOfBounds

fun PointerInputChange.isOutOfBounds(size: IntSize): Boolean

Returns true if the pointer has moved outside of the region of (0, 0, size.width, size.height) or false if the current pointer is up or it is inside the given bounds.

isOutOfBounds

fun PointerInputChange.isOutOfBounds(
    size: IntSize,
    extendedTouchPadding: Size
): Boolean

Returns true if the pointer has moved outside of the pointer region. For Touch events, this is (-extendedTouchPadding.width, -extendedTouchPadding.height, size.width + extendedTouchPadding.width, size.height + extendedTouchPadding.height) and for other events, this is (0, 0, size.width, size.height). Returnsfalse if the current pointer is up or it is inside the pointer region.

isPressed

fun PointerButtons.isPressed(buttonIndex: Int): Boolean

Returns true when the button at buttonIndex is pressed and false when it isn't pressed. This method can handle buttons that haven't been assigned a designated purpose like isPrimaryPressed and isSecondaryPressed.

motionEventSpy

fun Modifier.motionEventSpy(watcher: (motionEvent: MotionEvent) -> Unit): Modifier

Calls watcher with each MotionEvent that the layout area or any child pointerInput receives. The MotionEvent may or may not have been transformed to the local coordinate system. The Compose View will be considered as handling the MotionEvent in the area that the motionEventSpy is active.

This method can only be used to observe MotionEvents and can not be used to capture an event stream.

watcher is called during the PointerEventPass.Initial pass.

Developers should use pointerInput to handle pointer input processing within Compose. motionEventSpy is only useful as part of Android View interoperability.

If you need to handle and consume MotionEvents, use pointerInteropFilter.

pointerHoverIcon

fun Modifier.pointerHoverIcon(
    icon: PointerIcon,
    overrideDescendants: Boolean = false
): Modifier

Modifier that lets a developer define a pointer icon to display when the cursor is hovered over the element. When overrideDescendants is set to true, descendants cannot override the pointer icon using this modifier.

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.PointerIcon
import androidx.compose.ui.input.pointer.pointerHoverIcon

Column(Modifier.pointerHoverIcon(PointerIcon.Crosshair)) {
    SelectionContainer {
        Column {
            Text("Selectable text")
            Text(
                modifier = Modifier.pointerHoverIcon(PointerIcon.Hand, true),
                text = "Selectable text with hand"
            )
        }
    }
    Text("Just text with global pointerIcon")
}
Parameters
icon: PointerIcon

The icon to set

overrideDescendants: Boolean = false

when false (by default) descendants are able to set their own pointer icon. If true, no descendants under this parent are eligible to change the icon (it will be set to the this the parent's icon).

pointerInput

fun Modifier.pointerInput(block: suspend PointerInputScope.() -> Unit): Modifier

Create a modifier for processing pointer input within the region of the modified element.

It is an error to call pointerInput without at least one key parameter.

pointerInput

fun Modifier.pointerInput(key1: Any?, block: PointerInputEventHandler): Modifier

Create a modifier for processing pointer input within the region of the modified element.

pointerInputs may call PointerInputScope.awaitPointerEventScope to install a pointer input handler that can AwaitPointerEventScope.awaitPointerEvent to receive and consume pointer input events. Extension functions on PointerInputScope or AwaitPointerEventScope may be defined to perform higher-level gesture detection. The pointer input handling block will be cancelled and re-started when pointerInput is recomposed with a different key1 or the block class is different.

When a pointerInput modifier is created by composition, if block captures any local variables to operate on, two patterns are common for working with changes to those variables depending on the desired behavior.

Specifying the captured value as a key parameter will cause block to cancel and restart from the beginning if the value changes:

import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput

@Composable
fun MyComposable(parameter: String) {
    Box(
        Modifier.fillMaxSize().pointerInput(parameter) {
            // This entire pointerInput block will restart from the beginning
            // if and when `parameter` changes, since it's used as a key in
            // the creation of the `pointerInput` modifier
            detectTapGestures { performAction(parameter) }
        }
    )
}

If block should not restart when a captured value is changed but the value should still be updated for its next use, use rememberUpdatedState to update a value holder that is accessed by block:

import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput

@Composable
fun MyComposable(parameter: String) {
    val currentParameter by rememberUpdatedState(parameter)
    Box(
        Modifier.fillMaxSize().pointerInput(Unit) {
            // This pointerInput block will never restart since
            // it specifies a key of `Unit`, which never changes
            detectTapGestures {
                // ...however, currentParameter is updated out from under this running
                // pointerInput suspend block by rememberUpdatedState, and will always
                // contain the latest value updated by the composition when a tap
                // is detected here.
                performAction(currentParameter)
            }
        }
    )
}

Note Any removal operations on Android Views from pointerInput should wrap the block in a post { } block to guarantee the event dispatch completes before executing the removal. (You do not need to do this when removing a composable because Compose guarantees it completes via the snapshot state system.)

pointerInput

fun Modifier.pointerInput(vararg keys: Any?, block: PointerInputEventHandler): Modifier

Create a modifier for processing pointer input within the region of the modified element.

pointerInputs may call PointerInputScope.awaitPointerEventScope to install a pointer input handler that can AwaitPointerEventScope.awaitPointerEvent to receive and consume pointer input events. Extension functions on PointerInputScope or AwaitPointerEventScope may be defined to perform higher-level gesture detection. The pointer input handling block will be cancelled and re-started when pointerInput is recomposed with any different keys or the block class is different.

When a pointerInput modifier is created by composition, if block captures any local variables to operate on, two patterns are common for working with changes to those variables depending on the desired behavior.

Specifying the captured value as a key parameter will cause block to cancel and restart from the beginning if the value changes:

import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput

@Composable
fun MyComposable(parameter: String) {
    Box(
        Modifier.fillMaxSize().pointerInput(parameter) {
            // This entire pointerInput block will restart from the beginning
            // if and when `parameter` changes, since it's used as a key in
            // the creation of the `pointerInput` modifier
            detectTapGestures { performAction(parameter) }
        }
    )
}

If block should not restart when a captured value is changed but the value should still be updated for its next use, use rememberUpdatedState to update a value holder that is accessed by block:

import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput

@Composable
fun MyComposable(parameter: String) {
    val currentParameter by rememberUpdatedState(parameter)
    Box(
        Modifier.fillMaxSize().pointerInput(Unit) {
            // This pointerInput block will never restart since
            // it specifies a key of `Unit`, which never changes
            detectTapGestures {
                // ...however, currentParameter is updated out from under this running
                // pointerInput suspend block by rememberUpdatedState, and will always
                // contain the latest value updated by the composition when a tap
                // is detected here.
                performAction(currentParameter)
            }
        }
    )
}

Note Any removal operations on Android Views from pointerInput should wrap the block in a post { } block to guarantee the event dispatch completes before executing the removal. (You do not need to do this when removing a composable because Compose guarantees it completes via the snapshot state system.)

pointerInput

fun Modifier.pointerInput(
    key1: Any?,
    key2: Any?,
    block: PointerInputEventHandler
): Modifier

Create a modifier for processing pointer input within the region of the modified element.

pointerInputs may call PointerInputScope.awaitPointerEventScope to install a pointer input handler that can AwaitPointerEventScope.awaitPointerEvent to receive and consume pointer input events. Extension functions on PointerInputScope or AwaitPointerEventScope may be defined to perform higher-level gesture detection. The pointer input handling block will be cancelled and re-started when pointerInput is recomposed with a different key1 or key2, or the block class is different.

When a pointerInput modifier is created by composition, if block captures any local variables to operate on, two patterns are common for working with changes to those variables depending on the desired behavior.

Specifying the captured value as a key parameter will cause block to cancel and restart from the beginning if the value changes:

import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput

@Composable
fun MyComposable(parameter: String) {
    Box(
        Modifier.fillMaxSize().pointerInput(parameter) {
            // This entire pointerInput block will restart from the beginning
            // if and when `parameter` changes, since it's used as a key in
            // the creation of the `pointerInput` modifier
            detectTapGestures { performAction(parameter) }
        }
    )
}

If block should not restart when a captured value is changed but the value should still be updated for its next use, use rememberUpdatedState to update a value holder that is accessed by block:

import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput

@Composable
fun MyComposable(parameter: String) {
    val currentParameter by rememberUpdatedState(parameter)
    Box(
        Modifier.fillMaxSize().pointerInput(Unit) {
            // This pointerInput block will never restart since
            // it specifies a key of `Unit`, which never changes
            detectTapGestures {
                // ...however, currentParameter is updated out from under this running
                // pointerInput suspend block by rememberUpdatedState, and will always
                // contain the latest value updated by the composition when a tap
                // is detected here.
                performAction(currentParameter)
            }
        }
    )
}

Note Any removal operations on Android Views from pointerInput should wrap the block in a post { } block to guarantee the event dispatch completes before executing the removal. (You do not need to do this when removing a composable because Compose guarantees it completes via the snapshot state system.)

pointerInteropFilter

fun Modifier.pointerInteropFilter(
    requestDisallowInterceptTouchEvent: RequestDisallowInterceptTouchEvent? = null,
    onTouchEvent: (MotionEvent) -> Boolean
): Modifier

A special PointerInputModifier that provides access to the underlying MotionEvents originally dispatched to Compose. Prefer pointerInput and use this only for interoperation with existing code that consumes MotionEvents.

While the main intent of this Modifier is to allow arbitrary code to access the original MotionEvent dispatched to Compose, for completeness, analogs are provided to allow arbitrary code to interact with the system as if it were an Android View.

This includes 2 APIs,

  1. onTouchEvent has a Boolean return type which is akin to the return type of View.onTouchEvent. If the provided onTouchEvent returns true, it will continue to receive the event stream (unless the event stream has been intercepted) and if it returns false, it will not.

  2. requestDisallowInterceptTouchEvent is a lambda that you can optionally provide so that you can later call it (yes, in this case, you call the lambda that you provided) which is akin to calling ViewParent.requestDisallowInterceptTouchEvent. When this is called, any associated ancestors in the tree that abide by the contract will act accordingly and will not intercept the even stream.

positionChange

fun PointerInputChange.positionChange(): Offset

The distance that the pointer has moved on the screen minus any distance that has been consumed.

positionChangeConsumed

fun PointerInputChange.positionChangeConsumed(): Boolean

True if this PointerInputChange's movement has been consumed.

positionChangeIgnoreConsumed

fun PointerInputChange.positionChangeIgnoreConsumed(): Offset

The distance that the pointer has moved on the screen, ignoring the fact that it might have been consumed.

positionChanged

fun PointerInputChange.positionChanged(): Boolean

True if this PointerInputChange represents a pointer moving on the screen and some of that movement has not been consumed.

positionChangedIgnoreConsumed

fun PointerInputChange.positionChangedIgnoreConsumed(): Boolean

True if this PointerInputChange represents a pointer moving on the screen ignoring how much of that movement may have been consumed.

Extension properties

areAnyPressed

val PointerButtons.areAnyPressedBoolean

Returns true if any button is pressed or false if all buttons are released.

isAltGraphPressed

val PointerKeyboardModifiers.isAltGraphPressedBoolean

true when the AltGraph key is pressed.

isAltPressed

val PointerKeyboardModifiers.isAltPressedBoolean

true when the Alt key is pressed. This is commonly associated with the Option key on some keyboards.

isBackPressed

val PointerButtons.isBackPressedBoolean

true when the back button (mouse back button) is pressed or false when it isn't pressed or there is no mouse button assigned to "back."

isCapsLockOn

val PointerKeyboardModifiers.isCapsLockOnBoolean

true when the keyboard's Caps Lock is on.

isCtrlPressed

val PointerKeyboardModifiers.isCtrlPressedBoolean

true when the Control key is pressed.

isForwardPressed

val PointerButtons.isForwardPressedBoolean

true when the forward button (mouse forward button) is pressed or false when it isn't pressed or there is no button assigned to "forward."

isFunctionPressed

val PointerKeyboardModifiers.isFunctionPressedBoolean

true when the Function key is pressed.

isMetaPressed

val PointerKeyboardModifiers.isMetaPressedBoolean

true when the Meta key is pressed. This is commonly associated with the Windows or Command key on some keyboards.

isNumLockOn

val PointerKeyboardModifiers.isNumLockOnBoolean

true when the keyboard's Num Lock is on.

isPrimaryPressed

val PointerButtons.isPrimaryPressedBoolean

true when the primary button (left mouse button) is pressed or false when it isn't pressed.

isScrollLockOn

val PointerKeyboardModifiers.isScrollLockOnBoolean

true when the keyboard's Scroll Lock is on.

isSecondaryPressed

val PointerButtons.isSecondaryPressedBoolean

true when the secondary button (right mouse button) is pressed or false when it isn't pressed.

isShiftPressed

val PointerKeyboardModifiers.isShiftPressedBoolean

true when the Shift key is pressed.

isSymPressed

val PointerKeyboardModifiers.isSymPressedBoolean

true when the Sym key is pressed.

isTertiaryPressed

val PointerButtons.isTertiaryPressedBoolean

true when the tertiary button (middle mouse button) is pressed or false when it isn't pressed.