A scroll indicator that transitions to indicate that a scroll gesture is available to the user.
OneHandedGestureScalingLazyColumnSample
@Composable
fun OneHandedGestureScalingLazyColumnSample() {
val backDispatcherOwner = LocalOnBackPressedDispatcherOwner.current
val onClick =
remember<() -> Unit> { { backDispatcherOwner?.onBackPressedDispatcher?.onBackPressed() } }
val scrollState = rememberScalingLazyListState()
val buttonInteractionSource = remember { MutableInteractionSource() }
val buttonGestureConfig =
rememberOneHandedGestureConfiguration(
action = GestureAction.Primary,
priority = GesturePriority.Clickable,
)
val buttonIndicatorState = remember { OneHandedGestureIndicatorState() }
val scrollGestureConfig =
rememberOneHandedGestureConfiguration(
action = GestureAction.Primary,
priority = GesturePriority.Scrollable,
)
val scrollIndicatorState = remember { OneHandedGestureIndicatorState() }
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(
gestureConfiguration = buttonGestureConfig,
interactionSource = buttonInteractionSource,
onGestureLabel = "close",
onGestureAvailable = { buttonIndicatorState.isIndicatorActive = true },
onGesture = onClick,
)
} then
Modifier.scrollable(
state = scrollState,
orientation = Orientation.Vertical,
reverseDirection = true,
overscrollEffect = rememberOverscrollEffect(),
),
) {
OneHandedGestureIndicator(buttonGestureConfig, buttonIndicatorState) {
Text("Close")
}
}
},
scrollIndicator = {
OneHandedGestureScrollIndicator(
gestureConfiguration = scrollGestureConfig,
indicatorState = scrollIndicatorState,
scrollState = scrollState,
modifier = Modifier.align(Alignment.CenterEnd),
)
},
) { contentPadding ->
ScalingLazyColumn(
state = scrollState,
contentPadding = contentPadding,
modifier =
Modifier.fillMaxSize()
.oneHandedGesture(
gestureConfiguration = scrollGestureConfig,
onGestureLabel = "scroll",
onGestureAvailable = { scrollIndicatorState.isIndicatorActive = true },
onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) },
),
autoCentering = null,
) {
items(10) { Text("Item $it") }
}
}
}
@Composable
fun OneHandedGestureTransformingLazyColumnSample() {
val backDispatcherOwner = LocalOnBackPressedDispatcherOwner.current
val onClick =
remember<() -> Unit> { { backDispatcherOwner?.onBackPressedDispatcher?.onBackPressed() } }
val scrollState = rememberTransformingLazyColumnState()
val buttonInteractionSource = remember { MutableInteractionSource() }
val buttonGestureConfig =
rememberOneHandedGestureConfiguration(
action = GestureAction.Primary,
priority = GesturePriority.Clickable,
)
val buttonIndicatorState = remember { OneHandedGestureIndicatorState() }
val scrollGestureConfig =
rememberOneHandedGestureConfiguration(
action = GestureAction.Primary,
priority = GesturePriority.Scrollable,
)
val scrollIndicatorState = remember { OneHandedGestureIndicatorState() }
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(
gestureConfiguration = buttonGestureConfig,
interactionSource = buttonInteractionSource,
onGestureLabel = "close",
onGestureAvailable = { buttonIndicatorState.isIndicatorActive = true },
onGesture = onClick,
)
} then
Modifier.scrollable(
state = scrollState,
orientation = Orientation.Vertical,
reverseDirection = true,
overscrollEffect = rememberOverscrollEffect(),
),
) {
OneHandedGestureIndicator(buttonGestureConfig, buttonIndicatorState) {
Text("Close")
}
}
},
scrollIndicator = {
OneHandedGestureScrollIndicator(
gestureConfiguration = scrollGestureConfig,
indicatorState = scrollIndicatorState,
scrollState = scrollState,
modifier = Modifier.align(Alignment.CenterEnd),
)
},
) { contentPadding ->
TransformingLazyColumn(
state = scrollState,
contentPadding = contentPadding,
modifier =
Modifier.fillMaxSize()
.oneHandedGesture(
gestureConfiguration = scrollGestureConfig,
onGestureLabel = "scroll",
onGestureAvailable = { scrollIndicatorState.isIndicatorActive = true },
onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) },
),
) {
items(10) { Text("Item $it") }
}
}
}