@@ -34,10 +34,10 @@ import androidx.compose.foundation.pager.HorizontalPager
3434import androidx.compose.foundation.pager.PagerState
3535import androidx.compose.foundation.pager.rememberPagerState
3636import androidx.compose.runtime.Composable
37- import androidx.compose.runtime.LaunchedEffect
37+ import androidx.compose.runtime.CompositionLocalProvider
3838import androidx.compose.runtime.MutableState
39+ import androidx.compose.runtime.compositionLocalOf
3940import androidx.compose.runtime.getValue
40- import androidx.compose.runtime.mutableIntStateOf
4141import androidx.compose.runtime.mutableStateOf
4242import androidx.compose.runtime.remember
4343import androidx.compose.runtime.rememberCoroutineScope
@@ -136,19 +136,17 @@ data class UIState(
136136 val isWideScreen : Boolean = false ,
137137)
138138
139+ val LocalPagerState = compositionLocalOf<PagerState > { error(" No pager state" ) }
140+ val LocalHandlePageChange = compositionLocalOf< (Int ) -> Unit > { error(" No handle page change" ) }
141+
139142@Composable
140143fun UITest (
141144 colorMode : MutableState <Int >,
142145) {
143146 val topAppBarScrollBehaviorList = List (UIConstants .PAGE_COUNT ) { MiuixScrollBehavior () }
144147 val pagerState = rememberPagerState(pageCount = { UIConstants .PAGE_COUNT })
145148 val coroutineScope = rememberCoroutineScope()
146- var selectedPage by remember { mutableIntStateOf(pagerState.currentPage) }
147- val currentScrollBehavior = topAppBarScrollBehaviorList[selectedPage]
148-
149- LaunchedEffect (pagerState.settledPage) {
150- if (selectedPage != pagerState.settledPage) selectedPage = pagerState.settledPage
151- }
149+ val currentScrollBehavior = topAppBarScrollBehaviorList[pagerState.currentPage]
152150
153151 val navigationItems = remember {
154152 listOf (
@@ -162,46 +160,44 @@ fun UITest(
162160 val showTopPopup = remember { mutableStateOf(false ) }
163161 val windowSize by rememberUpdatedState(getWindowSize())
164162
165- val onPageSelected : (Int ) -> Unit = remember {
163+ val handlePageChange : (Int ) -> Unit = remember(pagerState, coroutineScope) {
166164 { page ->
167- selectedPage = page
168165 coroutineScope.launch { pagerState.animateScrollToPage(page) }
169166 }
170167 }
171168
172- BoxWithConstraints (
173- modifier = Modifier .fillMaxSize()
169+ CompositionLocalProvider (
170+ LocalPagerState provides pagerState,
171+ LocalHandlePageChange provides handlePageChange
174172 ) {
175- val isWideScreen = maxWidth > UIConstants .WIDE_SCREEN_THRESHOLD
176- uiState = uiState.copy(isWideScreen = isWideScreen)
173+ BoxWithConstraints (
174+ modifier = Modifier .fillMaxSize()
175+ ) {
176+ val isWideScreen = maxWidth > UIConstants .WIDE_SCREEN_THRESHOLD
177+ uiState = uiState.copy(isWideScreen = isWideScreen)
177178
178- if (isWideScreen) {
179- WideScreenLayout (
180- selectedPage = selectedPage,
181- navigationItems = navigationItems,
182- uiState = uiState,
183- onUiStateChange = { uiState = it },
184- onPageSelected = onPageSelected,
185- showTopPopup = showTopPopup,
186- pagerState = pagerState,
187- topAppBarScrollBehaviorList = topAppBarScrollBehaviorList,
188- currentScrollBehavior = currentScrollBehavior,
189- windowSize = windowSize,
190- colorMode = colorMode
191- )
192- } else {
193- CompactScreenLayout (
194- selectedPage = selectedPage,
195- navigationItems = navigationItems,
196- uiState = uiState,
197- onUiStateChange = { uiState = it },
198- onPageSelected = onPageSelected,
199- showTopPopup = showTopPopup,
200- pagerState = pagerState,
201- topAppBarScrollBehaviorList = topAppBarScrollBehaviorList,
202- currentScrollBehavior = currentScrollBehavior,
203- colorMode = colorMode
204- )
179+ if (isWideScreen) {
180+ WideScreenLayout (
181+ navigationItems = navigationItems,
182+ uiState = uiState,
183+ onUiStateChange = { uiState = it },
184+ showTopPopup = showTopPopup,
185+ topAppBarScrollBehaviorList = topAppBarScrollBehaviorList,
186+ currentScrollBehavior = currentScrollBehavior,
187+ windowSize = windowSize,
188+ colorMode = colorMode
189+ )
190+ } else {
191+ CompactScreenLayout (
192+ navigationItems = navigationItems,
193+ uiState = uiState,
194+ onUiStateChange = { uiState = it },
195+ showTopPopup = showTopPopup,
196+ topAppBarScrollBehaviorList = topAppBarScrollBehaviorList,
197+ currentScrollBehavior = currentScrollBehavior,
198+ colorMode = colorMode
199+ )
200+ }
205201 }
206202 }
207203
@@ -221,13 +217,10 @@ fun UITest(
221217
222218@Composable
223219private fun WideScreenLayout (
224- selectedPage : Int ,
225220 navigationItems : List <NavigationItem >,
226221 uiState : UIState ,
227222 onUiStateChange : (UIState ) -> Unit ,
228- onPageSelected : (Int ) -> Unit ,
229223 showTopPopup : MutableState <Boolean >,
230- pagerState : PagerState ,
231224 topAppBarScrollBehaviorList : List <ScrollBehavior >,
232225 currentScrollBehavior : ScrollBehavior ,
233226 windowSize : WindowSize ,
@@ -240,8 +233,6 @@ private fun WideScreenLayout(
240233 Row {
241234 Box (modifier = Modifier .weight(0.4f )) {
242235 WideScreenPanel (
243- selectedPage = selectedPage,
244- onPageSelected = onPageSelected,
245236 barScrollBehavior = barScrollBehavior,
246237 uiState = uiState,
247238 windowSize = windowSize,
@@ -253,12 +244,9 @@ private fun WideScreenLayout(
253244 )
254245 Box (modifier = Modifier .weight(0.6f )) {
255246 WideScreenContent (
256- selectedPage = selectedPage,
257247 navigationItems = navigationItems,
258248 uiState = uiState,
259- onPageSelected = onPageSelected,
260249 showTopPopup = showTopPopup,
261- pagerState = pagerState,
262250 topAppBarScrollBehaviorList = topAppBarScrollBehaviorList,
263251 currentScrollBehavior = currentScrollBehavior,
264252 onUiStateChange = onUiStateChange,
@@ -271,13 +259,13 @@ private fun WideScreenLayout(
271259
272260@Composable
273261private fun WideScreenPanel (
274- selectedPage : Int ,
275- onPageSelected : (Int ) -> Unit ,
276262 barScrollBehavior : ScrollBehavior ,
277263 uiState : UIState ,
278264 windowSize : WindowSize ,
279265 layoutDirection : LayoutDirection
280266) {
267+ val currentPage = LocalPagerState .current.currentPage
268+ val handlePageChange = LocalHandlePageChange .current
281269 Scaffold (
282270 modifier = Modifier
283271 .padding(start = 18 .dp, end = 12 .dp)
@@ -312,8 +300,8 @@ private fun WideScreenPanel(
312300 UIConstants .PAGE_TITLES .forEachIndexed { index, title ->
313301 BasicComponent (
314302 title = title,
315- onClick = { onPageSelected (index) },
316- holdDownState = selectedPage == index,
303+ onClick = { handlePageChange (index) },
304+ holdDownState = currentPage == index,
317305 )
318306 }
319307 }
@@ -324,12 +312,9 @@ private fun WideScreenPanel(
324312
325313@Composable
326314private fun WideScreenContent (
327- selectedPage : Int ,
328315 navigationItems : List <NavigationItem >,
329316 uiState : UIState ,
330- onPageSelected : (Int ) -> Unit ,
331317 showTopPopup : MutableState <Boolean >,
332- pagerState : PagerState ,
333318 topAppBarScrollBehaviorList : List <ScrollBehavior >,
334319 currentScrollBehavior : ScrollBehavior ,
335320 onUiStateChange : (UIState ) -> Unit ,
@@ -346,14 +331,12 @@ private fun WideScreenContent(
346331 exit = fadeOut() + shrinkVertically()
347332 ) {
348333 SmallTopAppBar (
349- title = UIConstants .PAGE_TITLES [selectedPage ],
334+ title = UIConstants .PAGE_TITLES [LocalPagerState .current.currentPage ],
350335 scrollBehavior = currentScrollBehavior,
351336 actions = {
352337 TopAppBarActions (
353- selectedPage = selectedPage,
354338 items = navigationItems,
355- showTopPopup = showTopPopup,
356- onPageSelected = onPageSelected
339+ showTopPopup = showTopPopup
357340 )
358341 },
359342 defaultWindowInsetsPadding = false ,
@@ -381,7 +364,6 @@ private fun WideScreenContent(
381364 .imePadding()
382365 .windowInsetsPadding(WindowInsets .displayCutout.only(WindowInsetsSides .End ))
383366 .windowInsetsPadding(WindowInsets .navigationBars.only(WindowInsetsSides .End )),
384- pagerState = pagerState,
385367 topAppBarScrollBehaviorList = topAppBarScrollBehaviorList,
386368 padding = PaddingValues (
387369 end = padding.calculateEndPadding(LayoutDirection .Ltr ),
@@ -397,13 +379,10 @@ private fun WideScreenContent(
397379
398380@Composable
399381private fun CompactScreenLayout (
400- selectedPage : Int ,
401382 navigationItems : List <NavigationItem >,
402383 uiState : UIState ,
403384 onUiStateChange : (UIState ) -> Unit ,
404- onPageSelected : (Int ) -> Unit ,
405385 showTopPopup : MutableState <Boolean >,
406- pagerState : PagerState ,
407386 topAppBarScrollBehaviorList : List <ScrollBehavior >,
408387 currentScrollBehavior : ScrollBehavior ,
409388 colorMode : MutableState <Int >
@@ -421,10 +400,8 @@ private fun CompactScreenLayout(
421400 scrollBehavior = currentScrollBehavior,
422401 actions = {
423402 TopAppBarActions (
424- selectedPage = selectedPage,
425403 items = navigationItems,
426- showTopPopup = showTopPopup,
427- onPageSelected = onPageSelected
404+ showTopPopup = showTopPopup
428405 )
429406 }
430407 )
@@ -434,8 +411,6 @@ private fun CompactScreenLayout(
434411 NavigationBar (
435412 uiState = uiState,
436413 navigationItems = navigationItems,
437- selectedPage = selectedPage,
438- onPageSelected = onPageSelected
439414 )
440415 },
441416 floatingActionButton = {
@@ -455,7 +430,6 @@ private fun CompactScreenLayout(
455430 .imePadding()
456431 .windowInsetsPadding(WindowInsets .displayCutout.only(WindowInsetsSides .Horizontal ))
457432 .windowInsetsPadding(WindowInsets .navigationBars.only(WindowInsetsSides .Horizontal )),
458- pagerState = pagerState,
459433 topAppBarScrollBehaviorList = topAppBarScrollBehaviorList,
460434 padding = padding,
461435 uiState = uiState,
@@ -469,9 +443,9 @@ private fun CompactScreenLayout(
469443private fun NavigationBar (
470444 uiState : UIState ,
471445 navigationItems : List <NavigationItem >,
472- selectedPage : Int ,
473- onPageSelected : (Int ) -> Unit
474446) {
447+ val currentPage = LocalPagerState .current.currentPage
448+ val handlePageChange = LocalHandlePageChange .current
475449 AnimatedVisibility (
476450 visible = uiState.showNavigationBar,
477451 enter = fadeIn() + expandVertically(),
@@ -484,8 +458,8 @@ private fun NavigationBar(
484458 ) {
485459 NavigationBar (
486460 items = navigationItems,
487- selected = selectedPage ,
488- onClick = onPageSelected
461+ selected = currentPage ,
462+ onClick = handlePageChange
489463 )
490464 }
491465 AnimatedVisibility (
@@ -495,10 +469,11 @@ private fun NavigationBar(
495469 ) {
496470 FloatingNavigationBar (
497471 items = navigationItems,
498- selected = selectedPage ,
472+ selected = currentPage ,
499473 mode = FloatingNavigationBarDisplayMode .fromInt(uiState.floatingNavigationBarMode).toMode(),
500- horizontalAlignment = FloatingNavigationBarAlignment .fromInt(uiState.floatingNavigationBarPosition).toAlignment(),
501- onClick = onPageSelected
474+ horizontalAlignment = FloatingNavigationBarAlignment .fromInt(uiState.floatingNavigationBarPosition)
475+ .toAlignment(),
476+ onClick = handlePageChange
502477 )
503478 }
504479 }
@@ -617,12 +592,12 @@ private fun FloatingNavigationBarAlignment.toAlignment(): Alignment.Horizontal =
617592
618593@Composable
619594private fun TopAppBarActions (
620- selectedPage : Int ,
621595 items : List <NavigationItem >,
622596 showTopPopup : MutableState <Boolean >,
623- onPageSelected : (Int ) -> Unit
624597) {
625598 val hapticFeedback = LocalHapticFeedback .current
599+ val currentPage = LocalPagerState .current.currentPage
600+ val handlePageChange = LocalHandlePageChange .current
626601
627602 ListPopup (
628603 show = showTopPopup,
@@ -638,9 +613,9 @@ private fun TopAppBarActions(
638613 DropdownImpl (
639614 text = navigationItem.label,
640615 optionSize = items.size,
641- isSelected = index == selectedPage ,
616+ isSelected = index == currentPage ,
642617 onSelectedIndexChange = {
643- onPageSelected (index)
618+ handlePageChange (index)
644619 hapticFeedback.performHapticFeedback(HapticFeedbackType .Confirm )
645620 showTopPopup.value = false
646621 },
@@ -668,15 +643,14 @@ private fun TopAppBarActions(
668643@Composable
669644fun AppPager (
670645 modifier : Modifier = Modifier ,
671- pagerState : PagerState ,
672646 topAppBarScrollBehaviorList : List <ScrollBehavior >,
673647 padding : PaddingValues ,
674648 uiState : UIState ,
675649 onUiStateChange : (UIState ) -> Unit ,
676650 colorMode : MutableState <Int >
677651) {
678652 HorizontalPager (
679- state = pagerState ,
653+ state = LocalPagerState .current ,
680654 modifier = modifier,
681655 userScrollEnabled = uiState.enablePageUserScroll,
682656 beyondViewportPageCount = 1 ,
0 commit comments