Compose Wear OS Navigation & Rotary Input

512 Views Asked by At

I'm not able to get Rotary Input working on Wear OS compose app when I use navigation between two Scaffold composables with ScalingLazyColumns.

I'm using simple navigation to navigate between two scaffold composables (each of them with scalinglazycolumn).

        SwipeDismissableNavHost(
            //modifier = Modifier.background(Color.Black),
            navController = navController,
            startDestination = "main_screen"
        ) {
            composable("settings") {
                Settings(
                    coroutineScope = coroutineScope,
                    viewModel = viewModel,
                    context = context,
                    ...
                    )
            }
            composable("main_screen") {
                    TodayWeatherLayout(
                        coroutineScope = coroutineScope,
                        navController = navController,
                        context = context,
                        scope = scope,
                        viewModel = viewModel,
                        ...
                    )
                } 
}

From the main_screen, I'm entering settings on a button click

                onClick = {
                    navController.navigate("settings")
                }

This is how both composable screens look like

    Scaffold(
        modifier = Modifier.fillMaxSize(),
        timeText = { TimeText(
            modifier = Modifier.scrollAway(listState, itemIndex = 0, offset = 80.dp),
            timeSource = TimeTextDefaults.timeSource(format),

            ) },
        positionIndicator = { PositionIndicator(scalingLazyListState = listState) }
    ){        

val focusRequester = remember { FocusRequester() }
LaunchedEffect(Unit){focusRequester.requestFocus()}

ScalingLazyColumn(
            modifier = Modifier
                .fillMaxSize()
                .onRotaryScrollEvent {
                    coroutineScope.launch {
                        listState.scrollBy(it.verticalScrollPixels * 2)
                        listState.animateScrollBy(0f)
                    }
                    true
                }
                .focusRequester(focusRequester)
                .focusable(),
            //anchorType = ScalingLazyListAnchorType.ItemStart,
            //autoCentering = AutoCenteringParams(itemIndex = 1),
            autoCentering = null,
            contentPadding = PaddingValues(start = 8.dp, end = 8.dp, top = 40.dp, bottom = 60.dp),
            state = listState,
        ){
.... [COLUMN ITEMS]
}
}

Scrolling with Rotary Input unfortunately only works when I enter the app (main_screen). When I go into 'settings', I'm not able to scroll with rotating crown anymore. (Rotary Input). When I leave 'settings' Rotary Input does not work anymore also in the 'main_screen'.

In both screens I'm requesting focus with

    val focusRequester = remember { FocusRequester() }
    LaunchedEffect(Unit){focusRequester.requestFocus()}

Is there something wrong with my Navigation implementation? Swipe to scroll works fine in both 'main_screen' and 'settings'

In the logcat I can only see: 'Rotary event created but not consumed'

1

There are 1 best solutions below

1
On

Solved with

LaunchedEffect(Unit) {
            lifecycleOwner.repeatOnLifecycle(state = Lifecycle.State.RESUMED) {
                try {
                    focusRequester.requestFocus()
                } catch (e: IllegalStateException) {
                    Log.w(TAG, "Focus Requester not working", e)
                }
            }}

And

LocalView.current.viewTreeObserver.addOnWindowFocusChangeListener {
        if (it) {
            focusRequester.requestFocus()
        }
    }