onRotaryScrollEvent

Compose Modifier

Common
fun Modifier.onRotaryScrollEvent(onRotaryScrollEvent: (RotaryScrollEvent) -> Boolean): Modifier

Adding this modifier to the modifier parameter of a component will allow it to intercept RotaryScrollEvents if it (or one of its children) is focused.

Here is an example of a scrollable container that scrolls in response to RotaryScrollEvents.

This sample demonstrates how a parent can add an onRotaryScrollEvent modifier to gain access to a RotaryScrollEvent when a child does not consume it:

Parameters

onRotaryScrollEventThis callback is invoked when the user interacts with the rotary side button or the bezel on a wear device. While implementing this callback, return true to stop propagation of this event. If you return false, the event will be sent to this onRotaryScrollEvent's parent.

Returns

true if the event is consumed, false otherwise.

Code Examples

RotaryEventSample

@Composable
fun RotaryEventSample() {
    val scrollState = rememberScrollState()
    val coroutineScope = rememberCoroutineScope()
    val focusRequester = remember { FocusRequester() }
    Column(
        modifier =
            Modifier.fillMaxWidth()
                .verticalScroll(scrollState)
                .onRotaryScrollEvent {
                    coroutineScope.launch {
                        scrollState.scrollTo(
                            (scrollState.value + it.verticalScrollPixels).roundToInt()
                        )
                    }
                    true
                }
                .focusRequester(focusRequester)
                .focusable()
    ) {
        repeat(100) {
            Text(text = "item $it", modifier = Modifier.align(CenterHorizontally), color = White)
        }
    }
    LaunchedEffect(Unit) { focusRequester.requestFocus() }
}

PreRotaryEventSample

@Composable
fun PreRotaryEventSample() {
    MaterialTheme(colors = darkColors()) {
        val rowScrollState = rememberScrollState()
        val columnScrollState = rememberScrollState()
        val coroutineScope = rememberCoroutineScope()
        val focusRequester = remember { FocusRequester() }
        var interceptScroll by remember { mutableStateOf(false) }
        Column(
            Modifier.onPreRotaryScrollEvent {
                    // You can intercept an event before it is sent to the child.
                    if (interceptScroll) {
                        coroutineScope.launch { rowScrollState.scrollBy(it.horizontalScrollPixels) }
                        // return true to consume this event.
                        true
                    } else {
                        // return false to ignore this event and continue propagation to the child.
                        false
                    }
                }
                .onRotaryScrollEvent {
                    // If the child does not use the scroll, we get notified here.
                    coroutineScope.launch { rowScrollState.scrollBy(it.horizontalScrollPixels) }
                    true
                }
        ) {
            Row(
                modifier = Modifier.align(CenterHorizontally),
                verticalAlignment = CenterVertically,
            ) {
                Text(
                    modifier = Modifier.width(70.dp),
                    text = if (interceptScroll) "Row" else "Column",
                    style = TextStyle(color = White),
                )
                Switch(checked = interceptScroll, onCheckedChange = { interceptScroll = it })
            }
            Row(modifier = Modifier.fillMaxWidth().horizontalScroll(rowScrollState)) {
                repeat(100) {
                    Text(
                        text = "row item $it ",
                        modifier = Modifier.align(CenterVertically),
                        color = White,
                    )
                }
            }
            Column(
                modifier =
                    Modifier.fillMaxWidth()
                        .verticalScroll(columnScrollState)
                        .onRotaryScrollEvent {
                            coroutineScope.launch {
                                columnScrollState.scrollBy(it.verticalScrollPixels)
                            }
                            true
                        }
                        .focusRequester(focusRequester)
                        .focusable()
            ) {
                repeat(100) {
                    Text(
                        text = "column item $it",
                        modifier = Modifier.align(CenterHorizontally),
                        color = White,
                    )
                }
            }
        }
        LaunchedEffect(Unit) { focusRequester.requestFocus() }
    }
}