https://kotlinlang.org logo
#compose-wear
Title
# compose-wear
k

kevinskrei

03/05/2024, 3:34 PM
Hey everyone, I'm struggling to get the following scenario working: I have a root composable with a horizontal pager. The root view has a
TimerText
inside a
ScreenScaffold
. Each page of the pager has scrollable content. Is there a simple way to utilize the
scrollAway
method for the
TimerText
at the root while each child of the pager has its own scrolling state? I'm struggling to figure out how to pass the scrolling state up to the root. Any guidance would be much appreciated!
y

yschimke

03/05/2024, 5:15 PM
AppScaffold/ScreenScaffold should be smart enough to do this, if you are correctly handling focus.
Something like the following, I threw navigation in for the hell of it.
Copy code
val navController = rememberSwipeDismissableNavController()
    AppScaffold {
        SwipeDismissableNavHost(startDestination = "pager", navController = navController) {
            composable("pager") {
                val pagerState = rememberPagerState { 3 }

                // Could be just PagerScreen instead of PagerScaffold/HorizontalPager/HierarchicalFocusCoordinator
                PagerScaffold(
                    modifier = Modifier.fillMaxSize(),
                    pagerState = pagerState,
                ) {
                    HorizontalPager(
                        modifier = Modifier.fillMaxSize(),
                        state = pagerState,
                        flingBehavior = HorizontalPagerDefaults.flingParams(pagerState),
                    ) { page ->
                        HierarchicalFocusCoordinator(requiresFocus = { page == pagerState.currentPage }) {
                            val columnState = rememberResponsiveColumnState()
                            ScreenScaffold(scrollState = columnState) {
                                ScalingLazyColumn(
                                    modifier = Modifier.fillMaxSize(),
                                    columnState = rememberResponsiveColumnState()
                                ) {
                                    items(100) {
                                        Text(text = "Item $it")
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
AppScaffold and ScreenScaffold do the coordination that you are asking for.
Something didn't work, just checking.
I'll debug later. But generally it should work, possibly a bug or I'm missing something obvious.
k

kevinskrei

03/05/2024, 5:30 PM
Sounds good and thank you for your help. I didn't realize focus was important in this context. I'll give that a try!
y

yschimke

03/05/2024, 5:41 PM
Stupid bug in my code, calling
rememberResponsiveColumnState()
twice!
Simpler version
Copy code
val navController = rememberSwipeDismissableNavController()
    AppScaffold {
        SwipeDismissableNavHost(startDestination = "pager", navController = navController) {
            composable("pager") {
                val pagerState = rememberPagerState { 3 }

                PagerScreen(
                    modifier = Modifier.fillMaxSize(),
                    state = pagerState,
                ) {
                    val columnState = rememberResponsiveColumnState()
                    ScreenScaffold(scrollState = columnState) {
                        ScalingLazyColumn(
                            modifier = Modifier.fillMaxSize(),
                            columnState = columnState
                        ) {
                            items(100) {
                                Text(text = "Item $it")
                            }
                        }
                    }
                }
            }
        }
    }
pagerscroll.mp4
Focus is important for two reasons.
1. We need to know where to send RSB. Which page of the Pager, and even foreground/background of NavHost is on screen. Compose may have composed these even when offscreen. You can see this when you swipe between pages, or start a swipe to dismiss.
2. Since AppScaffold has a top level time text, and we want to animate between them, we need to know when to switch the scroll state controlling TimeText.
k

kevinskrei

03/05/2024, 7:49 PM
That makes a ton of sense. I appreciate the help. Just tried and your simple example works well! Thank you
👍 1
8 Views