Advertisement
Guest User

Untitled

a guest
Feb 18th, 2022
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 5.59 KB | None | 0 0
  1. @OptIn(ExperimentalPagerApi::class)
  2. @Composable
  3. fun HomeScreenToolbarContainer(
  4.   insets: Insets,
  5.   chanTheme: ChanTheme,
  6.   pagerState: PagerState,
  7.   // Each screen has Content() composable and also Toolbar composable. Content() is drawn inside of a
  8.   // HorizontalPager and Toolbar() is draw in this container.
  9.   childScreens: List<ComposeScreenWithToolbar>,
  10.   homeScreenViewModel: HomeScreenViewModel
  11. ) {
  12.   require(childScreens.isNotEmpty()) { "childScreens is empty!" }
  13.  
  14.   val currentPage = pagerState.currentPage.coerceIn(0, childScreens.lastIndex)
  15.   val targetPage = pagerState.targetPage.coerceIn(0, childScreens.lastIndex)
  16.   val animationProgress = pagerState.currentPageOffset
  17.  
  18.   val toolbarHeight = dimensionResource(id = R.dimen.toolbar_height)
  19.   val toolbarTranslationDistancePx = with(LocalDensity.current) { toolbarHeight.toPx() / 3f }
  20.   val toolbarTotalHeight = remember(key1 = insets.topDp) { insets.topDp + toolbarHeight }
  21.   val transitionIsProgress = currentPage != targetPage
  22.  
  23.   val postListScrollState = homeScreenViewModel.toolbarVisibilityInfo.postListScrollState.collectAsState()
  24.   val touchingTopOrBottomOfList by homeScreenViewModel.toolbarVisibilityInfo.postListTouchingTopOrBottomState.collectAsState()
  25.   val isDraggingPostList by homeScreenViewModel.toolbarVisibilityInfo.postListDragState.collectAsState()
  26.   val isDraggingFastScroller by homeScreenViewModel.toolbarVisibilityInfo.fastScrollerDragState.collectAsState()
  27.  
  28.   val toolbarAlpha by when {
  29.     isDraggingFastScroller -> animateFloatAsState(targetValue = 0f)
  30.     touchingTopOrBottomOfList -> animateFloatAsState(targetValue = 1f)
  31.     isDraggingPostList -> postListScrollState
  32.     else -> {
  33.       val targetValue = if (postListScrollState.value > 0.5f) 1f else 0f
  34.       animateFloatAsState(targetValue = targetValue)
  35.     }
  36.   }
  37.  
  38.   Column(
  39.     modifier = Modifier
  40.       .fillMaxWidth()
  41.       .height(toolbarTotalHeight)
  42.       .alpha(toolbarAlpha)
  43.       .background(chanTheme.primaryColorCompose)
  44.       .consumeClicks()
  45.   ) {
  46.     Spacer(modifier = Modifier.height(insets.topDp))
  47.  
  48.     Box(
  49.       modifier = Modifier
  50.         .fillMaxWidth()
  51.         .height(toolbarHeight)
  52.     ) {
  53.       val zOrders = remember(key1 = childScreens.size) { IntArray(childScreens.size) { 0 } }
  54.       var normalIndex = 0
  55.  
  56.       for ((pageIndex, _) in childScreens.withIndex()) {
  57.         when (pageIndex) {
  58.           // (Currently animated) Always behind the target and above everything else
  59.           currentPage -> zOrders[pageIndex] = 999
  60.           // (Currently animated) Always at the top
  61.           targetPage -> zOrders[pageIndex] = 1000
  62.           else -> zOrders[pageIndex] = normalIndex++
  63.         }
  64.       }
  65.  
  66.       for ((pageIndex, currentScreen) in childScreens.withIndex()) {
  67.         val zOrder = zOrders[pageIndex]
  68.  
  69.         when (pageIndex) {
  70.           currentPage -> {
  71.             val currentToolbarAlpha = lerpFloat(1f, 0f, Math.abs(animationProgress))
  72.             val currentToolbarTranslation = if (animationProgress >= 0f) {
  73.               lerpFloat(0f, toolbarTranslationDistancePx, Math.abs(animationProgress))
  74.             } else {
  75.               lerpFloat(0f, -toolbarTranslationDistancePx, Math.abs(animationProgress))
  76.             }
  77.  
  78.             BuildChildToolbar(
  79.               composeScreenWithToolbar = currentScreen,
  80.               zOrder = zOrder,
  81.               targetToolbarAlpha = currentToolbarAlpha,
  82.               targetToolbarTranslation = currentToolbarTranslation,
  83.               transitionIsProgress = transitionIsProgress
  84.             )
  85.           }
  86.           targetPage -> {
  87.             val targetToolbarAlpha = lerpFloat(0f, 1f, Math.abs(animationProgress))
  88.             val targetToolbarTranslation = if (animationProgress >= 0f) {
  89.               lerpFloat(-toolbarTranslationDistancePx, 0f, Math.abs(animationProgress))
  90.             } else {
  91.               lerpFloat(toolbarTranslationDistancePx, 0f, Math.abs(animationProgress))
  92.             }
  93.  
  94.             BuildChildToolbar(
  95.               composeScreenWithToolbar = currentScreen,
  96.               zOrder = zOrder,
  97.               targetToolbarAlpha = targetToolbarAlpha,
  98.               targetToolbarTranslation = targetToolbarTranslation,
  99.               transitionIsProgress = transitionIsProgress
  100.             )
  101.           }
  102.           else -> {
  103.             BuildChildToolbar(
  104.               composeScreenWithToolbar = currentScreen,
  105.               zOrder = zOrder,
  106.               targetToolbarAlpha = 0f,
  107.               targetToolbarTranslation = 0f,
  108.               transitionIsProgress = transitionIsProgress
  109.             )
  110.           }
  111.         }
  112.       }
  113.     }
  114.   }
  115. }
  116.  
  117. @Composable
  118. private fun BuildChildToolbar(
  119.   composeScreenWithToolbar: ComposeScreenWithToolbar,
  120.   zOrder: Int,
  121.   targetToolbarAlpha: Float,
  122.   targetToolbarTranslation: Float,
  123.   transitionIsProgress: Boolean
  124. ) {
  125.   key(composeScreenWithToolbar.screenKey) {
  126.     Box(
  127.       modifier = Modifier
  128.         .zIndex(zOrder.toFloat())
  129.         .graphicsLayer {
  130.           alpha = targetToolbarAlpha
  131.           translationY = targetToolbarTranslation
  132.         }
  133.         .consumeClicks(consume = transitionIsProgress)
  134.     ) {
  135.       DisposableEffect(
  136.         key1 = Unit,
  137.         effect = {
  138.           logcat(tag = "BuildChildToolbar") { "Toolbar of screen ${composeScreenWithToolbar.screenKey.key} composed" }
  139.  
  140.           // Every time the pager is dragged this is called for some unknown reason
  141.           onDispose { logcat(tag = "BuildChildToolbar") { "Toolbar of screen ${composeScreenWithToolbar.screenKey.key} disposed" } }
  142.         }
  143.       )
  144.  
  145.       composeScreenWithToolbar.Toolbar(this)
  146.     }
  147.   }
  148. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement