{% setvar book_path %}/reference/androidx/_book.yaml{% endsetvar %} {% include "_shared/_reference-head-tags.html" %}

PointerEvent

public final class PointerEvent


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

Summary

Public constructors

Public methods

final @NonNull List<@NonNull PointerInputChange>
final @NonNull PointerEvent
copy(
    @NonNull List<@NonNull PointerInputChange> changes,
    MotionEvent motionEvent
)
final @NonNull PointerButtons

The state of buttons (e.g. mouse or stylus buttons) during this event.

final @NonNull List<@NonNull PointerInputChange>

The changes.

final @NonNull PointerKeyboardModifiers

The state of modifier keys during this event.

final @NonNull PointerEventType

The primary reason the PointerEvent was sent.

Extension functions

final @NonNull Offset
TransformGestureDetectorKt.calculateCentroid(
    @NonNull PointerEvent receiver,
    boolean useCurrent
)

Returns the centroid of all pointers that are down and were previously down.

final float
TransformGestureDetectorKt.calculateCentroidSize(
    @NonNull PointerEvent receiver,
    boolean useCurrent
)

Returns the average distance from the centroid for all pointers that are currently and were previously down.

final @NonNull Offset

Returns the change in the centroid location between the previous and the current pointers that are down.

final float

Returns the rotation, in degrees, of the pointers between the PointerInputChange.previousPosition and PointerInputChange.position states.

final float

Uses the change of the centroid size between the PointerInputChange.previousPosition and PointerInputChange.position to determine how much zoom was intended.

Public constructors

PointerEvent

public PointerEvent(@NonNull List<@NonNull PointerInputChange> changes)
Parameters
@NonNull List<@NonNull PointerInputChange> changes

The changes.

Public methods

component1

public final @NonNull List<@NonNull PointerInputChangecomponent1()

copy

public final @NonNull PointerEvent copy(
    @NonNull List<@NonNull PointerInputChange> changes,
    MotionEvent motionEvent
)

getButtons

public final @NonNull PointerButtons getButtons()

The state of buttons (e.g. mouse or stylus buttons) during this event.

getChanges

public final @NonNull List<@NonNull PointerInputChangegetChanges()

The changes.

getKeyboardModifiers

public final @NonNull PointerKeyboardModifiers getKeyboardModifiers()

The state of modifier keys during this event.

getType

public final @NonNull PointerEventType getType()

The primary reason the PointerEvent was sent.

Extension functions

TransformGestureDetectorKt.calculateCentroid

public final @NonNull Offset TransformGestureDetectorKt.calculateCentroid(
    @NonNull PointerEvent receiver,
    boolean useCurrent
)

Returns the centroid of all pointers that are down and were previously down. If no pointers are down, Offset.Unspecified is returned. If useCurrent is true, the centroid of the PointerInputChange.position is returned and if false, the centroid of the PointerInputChange.previousPosition is returned. Only pointers that are down in both the previous and current state are used to calculate the centroid.

Example Usage:

import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.calculateCentroid
import androidx.compose.foundation.gestures.calculateCentroidSize
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput

var centroidSize by remember { mutableStateOf(0f) }
var position by remember { mutableStateOf(Offset.Zero) }
Box(
    Modifier
        .drawBehind {
            // Draw a circle where the gesture is
            drawCircle(Color.Blue, centroidSize, center = position)
        }
        .pointerInput(Unit) {
            awaitEachGesture {
                awaitFirstDown().also {
                    position = it.position
                }
                do {
                    val event = awaitPointerEvent()
                    val size = event.calculateCentroidSize()
                    if (size != 0f) {
                        centroidSize = event.calculateCentroidSize()
                    }
                    val centroid = event.calculateCentroid()
                    if (centroid != Offset.Unspecified) {
                        position = centroid
                    }
                } while (event.changes.any { it.pressed })
            }
        }
        .fillMaxSize()
)

TransformGestureDetectorKt.calculateCentroidSize

public final float TransformGestureDetectorKt.calculateCentroidSize(
    @NonNull PointerEvent receiver,
    boolean useCurrent
)

Returns the average distance from the centroid for all pointers that are currently and were previously down. If no pointers are down, 0 is returned. If useCurrent is true, the size of the PointerInputChange.position is returned and if false, the size of PointerInputChange.previousPosition is returned. Only pointers that are down in both the previous and current state are used to calculate the centroid size.

Example Usage:

import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.calculateCentroid
import androidx.compose.foundation.gestures.calculateCentroidSize
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput

var centroidSize by remember { mutableStateOf(0f) }
var position by remember { mutableStateOf(Offset.Zero) }
Box(
    Modifier
        .drawBehind {
            // Draw a circle where the gesture is
            drawCircle(Color.Blue, centroidSize, center = position)
        }
        .pointerInput(Unit) {
            awaitEachGesture {
                awaitFirstDown().also {
                    position = it.position
                }
                do {
                    val event = awaitPointerEvent()
                    val size = event.calculateCentroidSize()
                    if (size != 0f) {
                        centroidSize = event.calculateCentroidSize()
                    }
                    val centroid = event.calculateCentroid()
                    if (centroid != Offset.Unspecified) {
                        position = centroid
                    }
                } while (event.changes.any { it.pressed })
            }
        }
        .fillMaxSize()
)

TransformGestureDetectorKt.calculatePan

public final @NonNull Offset TransformGestureDetectorKt.calculatePan(@NonNull PointerEvent receiver)

Returns the change in the centroid location between the previous and the current pointers that are down. Pointers that are newly down or raised are not considered in the centroid movement.

Example Usage:

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.calculatePan
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.IntOffset

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
Box(
    Modifier
        .offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
        .graphicsLayer()
        .background(Color.Blue)
        .pointerInput(Unit) {
            awaitEachGesture {
                awaitFirstDown()
                do {
                    val event = awaitPointerEvent()
                    val offset = event.calculatePan()
                    offsetX.value += offset.x
                    offsetY.value += offset.y
                } while (event.changes.any { it.pressed })
            }
        }
        .fillMaxSize()
)

TransformGestureDetectorKt.calculateRotation

public final float TransformGestureDetectorKt.calculateRotation(
    @NonNull PointerEvent receiver
)

Returns the rotation, in degrees, of the pointers between the PointerInputChange.previousPosition and PointerInputChange.position states. Only the pointers that are down in both previous and current states are considered.

Example Usage:

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.calculateRotation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput

var angle by remember { mutableStateOf(0f) }
Box(
    Modifier
        .graphicsLayer(rotationZ = angle)
        .background(Color.Blue)
        .pointerInput(Unit) {
            awaitEachGesture {
                awaitFirstDown()
                do {
                    val event = awaitPointerEvent()
                    val rotation = event.calculateRotation()
                    angle += rotation
                } while (event.changes.any { it.pressed })
            }
        }
        .fillMaxSize()
)

TransformGestureDetectorKt.calculateZoom

public final float TransformGestureDetectorKt.calculateZoom(
    @NonNull PointerEvent receiver
)

Uses the change of the centroid size between the PointerInputChange.previousPosition and PointerInputChange.position to determine how much zoom was intended.

Example Usage:

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.calculateZoom
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput

var zoom by remember { mutableStateOf(1f) }
Box(
    Modifier
        .graphicsLayer(scaleX = zoom, scaleY = zoom)
        .background(Color.Blue)
        .pointerInput(Unit) {
            awaitEachGesture {
                awaitFirstDown()
                do {
                    val event = awaitPointerEvent()
                    zoom *= event.calculateZoom()
                } while (event.changes.any { it.pressed })
            }
        }
        .fillMaxSize()
)