OneHandedGestureScrollIndicator

Functions summary

Unit
@Composable
OneHandedGestureScrollIndicator(
    interactionSource: InteractionSource,
    state: ScalingLazyListState,
    modifier: Modifier,
    scrollIndicatorColors: ScrollIndicatorColors,
    gestureIndicatorTint: Color,
    gestureIndicatorBackgroundColor: Color,
    reverseDirection: Boolean,
    positionAnimationSpec: AnimationSpec<Float>
)

A scroll indicator that transitions to indicate that a scroll gesture is available to the user.

Unit
@Composable
OneHandedGestureScrollIndicator(
    interactionSource: InteractionSource,
    state: TransformingLazyColumnState,
    modifier: Modifier,
    scrollIndicatorColors: ScrollIndicatorColors,
    gestureIndicatorTint: Color,
    gestureIndicatorBackgroundColor: Color,
    reverseDirection: Boolean,
    positionAnimationSpec: AnimationSpec<Float>
)

A scroll indicator that transitions to indicate that a scroll gesture is available to the user.

Functions

OneHandedGestureScrollIndicator

@Composable
fun OneHandedGestureScrollIndicator(
    interactionSource: InteractionSource,
    state: ScalingLazyListState,
    modifier: Modifier = Modifier,
    scrollIndicatorColors: ScrollIndicatorColors = ScrollIndicatorDefaults.colors(),
    gestureIndicatorTint: Color = MaterialTheme.colorScheme.onTertiary,
    gestureIndicatorBackgroundColor: Color = MaterialTheme.colorScheme.tertiary,
    reverseDirection: Boolean = false,
    positionAnimationSpec: AnimationSpec<Float> = ScrollIndicatorDefaults.PositionAnimationSpec
): Unit

A scroll indicator that transitions to indicate that a scroll gesture is available to the user.

Under normal conditions, this component behaves like a standard scroll indicator, reflecting the current scroll position of a androidx.wear.compose.foundation.lazy.ScalingLazyColumn. It listens to the provided interactionSource to handle the visual transition into a gesture indicator. When a relevant gesture interaction is received, the indicator temporarily replaces its standard visual state with a gesture animation sequence. Once the animation completes, it automatically returns to its standard scroll indicator behavior.

Sample demonstrating a gesture indicator applied to a androidx.wear.compose.foundation.lazy.ScalingLazyColumn:

import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.rememberOverscrollEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.onehandedgesture.GestureAction
import androidx.wear.compose.material3.onehandedgesture.GesturePriority
import androidx.wear.compose.material3.onehandedgesture.OneHandedGestureDefaults
import androidx.wear.compose.material3.onehandedgesture.OneHandedGestureIndicator
import androidx.wear.compose.material3.onehandedgesture.OneHandedGestureScrollIndicator
import androidx.wear.compose.material3.onehandedgesture.oneHandedGesture

val backDispatcherOwner = LocalOnBackPressedDispatcherOwner.current
val onClick =
    remember<() -> Unit> { { backDispatcherOwner?.onBackPressedDispatcher?.onBackPressed() } }
val slcState = rememberScalingLazyListState()
val buttonInteractionSource = remember { MutableInteractionSource() }
val slcInteractionSource = remember { MutableInteractionSource() }

ScreenScaffold(
    scrollState = slcState,
    edgeButton = {
        EdgeButton(
            onClick = onClick,
            interactionSource = buttonInteractionSource,
            modifier =
                if (slcState.canScrollForward) {
                    Modifier
                } else {
                    // Apply the one-handed gesture modifier only when the container cannot
                    // scroll further, ensuring the EdgeButton is fully visible and interactive
                    Modifier.oneHandedGesture(
                        action = GestureAction.Primary,
                        priority = GesturePriority.Clickable,
                        interactionSource = buttonInteractionSource,
                        onGesture = onClick,
                    )
                } then
                    Modifier.scrollable(
                        state = slcState,
                        orientation = Orientation.Vertical,
                        reverseDirection = true,
                        overscrollEffect = rememberOverscrollEffect(),
                    ),
        ) {
            OneHandedGestureIndicator(interactionSource = buttonInteractionSource) {
                Text("Close")
            }
        }
    },
    scrollIndicator = {
        OneHandedGestureScrollIndicator(
            interactionSource = slcInteractionSource,
            state = slcState,
            modifier = Modifier.align(Alignment.CenterEnd),
        )
    },
) { contentPadding ->
    ScalingLazyColumn(
        state = slcState,
        contentPadding = contentPadding,
        modifier =
            Modifier.fillMaxSize()
                .oneHandedGesture(
                    action = GestureAction.Primary,
                    priority = GesturePriority.Scrollable,
                    interactionSource = slcInteractionSource,
                    onGesture = { OneHandedGestureDefaults.scrollDown(slcState) },
                ),
        autoCentering = null,
    ) {
        items(10) { Text("Item $it") }
    }
}
Parameters
interactionSource: InteractionSource

The InteractionSource stream to observe for incoming gesture indications. This is used to determine when the gesture animation sequence should be triggered.

state: ScalingLazyListState

The state object of the androidx.wear.compose.foundation.lazy.ScalingLazyColumn this indicator is coupled with.

modifier: Modifier = Modifier

The Modifier to be applied to the scroll indicator.

scrollIndicatorColors: ScrollIndicatorColors = ScrollIndicatorDefaults.colors()

ScrollIndicatorColors that will be used to resolve the indicator and track colors for this androidx.wear.compose.material3.ScrollIndicator.

gestureIndicatorTint: Color = MaterialTheme.colorScheme.onTertiary

The color which will be used for a tint of the gesture animation icon.

gestureIndicatorBackgroundColor: Color = MaterialTheme.colorScheme.tertiary

The color which will be used for a background behind the gesture animation.

reverseDirection: Boolean = false

Reverses direction of ScrollIndicator if true.

positionAnimationSpec: AnimationSpec<Float> = ScrollIndicatorDefaults.PositionAnimationSpec

AnimationSpec for position animation. The Position animation is used for animating changes to the scroll size and position. To disable this animation androidx.compose.animation.core.snap AnimationSpec should be passed instead.

OneHandedGestureScrollIndicator

@Composable
fun OneHandedGestureScrollIndicator(
    interactionSource: InteractionSource,
    state: TransformingLazyColumnState,
    modifier: Modifier = Modifier,
    scrollIndicatorColors: ScrollIndicatorColors = ScrollIndicatorDefaults.colors(),
    gestureIndicatorTint: Color = MaterialTheme.colorScheme.onTertiary,
    gestureIndicatorBackgroundColor: Color = MaterialTheme.colorScheme.tertiary,
    reverseDirection: Boolean = false,
    positionAnimationSpec: AnimationSpec<Float> = ScrollIndicatorDefaults.PositionAnimationSpec
): Unit

A scroll indicator that transitions to indicate that a scroll gesture is available to the user.

Under normal conditions, this component behaves like a standard scroll indicator, reflecting the current scroll position of a androidx.wear.compose.foundation.lazy.TransformingLazyColumn. It listens to the provided interactionSource to handle the visual transition into a gesture indicator. When a relevant gesture interaction is received, the indicator temporarily replaces its standard visual state with a gesture animation sequence. Once the animation completes, it automatically returns to its standard scroll indicator behavior.

Sample demonstrating a gesture indicator applied to a androidx.wear.compose.foundation.lazy.TransformingLazyColumn:

import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.rememberOverscrollEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.onehandedgesture.GestureAction
import androidx.wear.compose.material3.onehandedgesture.GesturePriority
import androidx.wear.compose.material3.onehandedgesture.OneHandedGestureDefaults
import androidx.wear.compose.material3.onehandedgesture.OneHandedGestureIndicator
import androidx.wear.compose.material3.onehandedgesture.OneHandedGestureScrollIndicator
import androidx.wear.compose.material3.onehandedgesture.oneHandedGesture

val backDispatcherOwner = LocalOnBackPressedDispatcherOwner.current
val onClick =
    remember<() -> Unit> { { backDispatcherOwner?.onBackPressedDispatcher?.onBackPressed() } }
val scrollState = rememberTransformingLazyColumnState()
val buttonInteractionSource = remember { MutableInteractionSource() }
val scrollInteractionSource = remember { MutableInteractionSource() }

ScreenScaffold(
    scrollState = scrollState,
    edgeButton = {
        EdgeButton(
            onClick = onClick,
            interactionSource = buttonInteractionSource,
            modifier =
                if (scrollState.canScrollForward) {
                    Modifier
                } else {
                    // Apply the one-handed gesture modifier only when the container cannot
                    // scroll further, ensuring the EdgeButton is fully visible and interactive
                    Modifier.oneHandedGesture(
                        action = GestureAction.Primary,
                        priority = GesturePriority.Clickable,
                        interactionSource = buttonInteractionSource,
                        onGesture = onClick,
                    )
                } then
                    Modifier.scrollable(
                        state = scrollState,
                        orientation = Orientation.Vertical,
                        reverseDirection = true,
                        overscrollEffect = rememberOverscrollEffect(),
                    ),
        ) {
            OneHandedGestureIndicator(interactionSource = buttonInteractionSource) {
                Text("Close")
            }
        }
    },
    scrollIndicator = {
        OneHandedGestureScrollIndicator(
            interactionSource = scrollInteractionSource,
            state = scrollState,
            modifier = Modifier.align(Alignment.CenterEnd),
        )
    },
) { contentPadding ->
    TransformingLazyColumn(
        state = scrollState,
        contentPadding = contentPadding,
        modifier =
            Modifier.fillMaxSize()
                .oneHandedGesture(
                    action = GestureAction.Primary,
                    priority = GesturePriority.Scrollable,
                    interactionSource = scrollInteractionSource,
                    onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) },
                ),
    ) {
        items(10) { Text("Item $it") }
    }
}
Parameters
interactionSource: InteractionSource

The InteractionSource stream to observe for incoming gesture indications. This is used to determine when the gesture animation sequence should be triggered.

state: TransformingLazyColumnState

The state object of the androidx.wear.compose.foundation.lazy.TransformingLazyColumn this indicator is coupled with.

modifier: Modifier = Modifier

The Modifier to be applied to the scroll indicator.

scrollIndicatorColors: ScrollIndicatorColors = ScrollIndicatorDefaults.colors()

ScrollIndicatorColors that will be used to resolve the indicator and track colors for this androidx.wear.compose.material3.ScrollIndicator.

gestureIndicatorTint: Color = MaterialTheme.colorScheme.onTertiary

The color which will be used for a tint of the gesture animation icon.

gestureIndicatorBackgroundColor: Color = MaterialTheme.colorScheme.tertiary

The color which will be used for a background behind the gesture animation.

reverseDirection: Boolean = false

Reverses direction of ScrollIndicator if true.

positionAnimationSpec: AnimationSpec<Float> = ScrollIndicatorDefaults.PositionAnimationSpec

AnimationSpec for position animation. The Position animation is used for animating changes to the scroll size and position. To disable this animation androidx.compose.animation.core.snap AnimationSpec should be passed instead.