OneHandedGestureScrollIndicator

Functions summary

Unit
@Composable
OneHandedGestureScrollIndicator(
    gestureIndicatorVisible: Boolean,
    onGestureIndicatorFinished: () -> Unit,
    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(
    gestureIndicatorVisible: Boolean,
    onGestureIndicatorFinished: () -> Unit,
    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. When gestureIndicatorVisible is set to true, the indicator temporarily replaces its standard visual state with a gesture animation sequence.

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.mutableStateOf
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 tlcState = rememberTransformingLazyColumnState()
var scrollGestureIndicatorVisible by remember { mutableStateOf(false) }
val interactionSource = remember { MutableInteractionSource() }

ScreenScaffold(
    scrollState = tlcState,
    edgeButton = {
        var buttonGestureIndicatorVisible by remember { mutableStateOf(false) }
        EdgeButton(
            onClick = onClick,
            interactionSource = interactionSource,
            modifier =
                if (tlcState.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 = interactionSource,
                        onShowIndicator = { buttonGestureIndicatorVisible = true },
                        onGesture = onClick,
                    )
                } then
                    Modifier.scrollable(
                        tlcState,
                        orientation = Orientation.Vertical,
                        reverseDirection = true,
                        overscrollEffect = rememberOverscrollEffect(),
                    ),
        ) {
            OneHandedGestureIndicator(
                buttonGestureIndicatorVisible,
                { buttonGestureIndicatorVisible = false },
            ) {
                Text("Close")
            }
        }
    },
    scrollIndicator = {
        OneHandedGestureScrollIndicator(
            scrollGestureIndicatorVisible,
            onGestureIndicatorFinished = { scrollGestureIndicatorVisible = false },
            tlcState,
            modifier = Modifier.align(Alignment.CenterEnd),
        )
    },
) { contentPadding ->
    TransformingLazyColumn(
        state = tlcState,
        contentPadding = contentPadding,
        modifier =
            Modifier.fillMaxSize()
                .oneHandedGesture(
                    action = GestureAction.Primary,
                    priority = GesturePriority.Scrollable,
                    onGesture = { OneHandedGestureDefaults.scrollDown(tlcState) },
                    onShowIndicator = { scrollGestureIndicatorVisible = true },
                ),
    ) {
        items(10) { Text("Item $it") }
    }
}
Parameters
gestureIndicatorVisible: Boolean

A boolean flag that triggers the gesture indicator animation. While true, the standard scroll indicator is transformed into the gesture indicator.

onGestureIndicatorFinished: () -> Unit

A lambda function to be called when the gesture indicator animation sequence finishes. Implementation of this lambda must reset gestureIndicatorVisible to false in order to restore the original content.

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.