How to focus the currently selected intem in a horizontalPager?

58 Views Asked by At

I am working on an wearOS app with a HorizonalPager, which has a ScalingLazyColumn in each of its pages. For all who aren't so familiar with wearOS design elements: A ScalingLazyColumn is basicly just a vertical List of different items. in my case some Cards. The code looks somewhat like this:

HorizontalPager(state=pagerState){
val listState = rememberScalingLazyListState()
val coroutineScope = rememberCoroutineScope()

ScalingLazyColumn(
state= listState,
modifier= modifier
.onRotaryScrollEvent {
   coroutineScope.launch {
      listState.scrollBy(it.verticalScrollPixels)
      listState.animateScrollBy(0f)}
                               
      true
   }
.focusRequester(focusRequester)
.focusable()
){

//in here are my items
}
}

In order for the Code to accept the rotary Input of smartwatches, I need the onRotaryScrollEvent to scroll the list.But for this to work, the List must have focus. The problem with this code is, that just the firstly loaded page is focused and nothing else.

So I would need some way to just focus the currently selected page of this HorizontalPager. Any Ideas?

Thanks!

1

There are 1 best solutions below

0
Yuri Schimke On

The horologist project has a wrapper for HorizontalPager that does this automatically, as well as the page indicator.

https://github.com/google/horologist/blob/4e139ff18cc3bbd275088a9f596883c3ef7bbc06/compose-layout/src/main/java/com/google/android/horologist/compose/pager/PagerScreen.kt#L48

You can use this directly, or copy the approach.

The critical code is HierarchicalFocusCoordinator, which can be hooked into navigation or pager scrolling to focus the right screen.

        HorizontalPager(
            modifier = modifier,
            state = state,
            flingBehavior = HorizontalPagerDefaults.flingParams(state),
        ) { page ->
            ClippedBox(state) {
                HierarchicalFocusCoordinator(requiresFocus = { page == state.currentPage }) {
                    content(page)
                }
            }
        }

Within your content, when you use Compose's rememberActiveFocusRequester() it will follow the current page.