Last active
October 5, 2020 13:19
Revisions
-
mayojava revised this gist
Oct 5, 2020 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -70,7 +70,7 @@ fun Pager( } fun Modifier.scrollOffset(orientation: Orientation, offset: Dp) = offset( x = if (orientation == Horizontal) offset else 0.dp, y = if (orientation == Vertical) offset else 0.dp ) @@ -99,7 +99,7 @@ private data class PagerState( val scrollController = ScrollableController( consumeScrollDelta = { scrollDelta -> val oldOffset = scrollOffset scrollOffset = (oldOffset + scrollDelta).coerceIn(-1 * maxPageFraction * pageDimen, 0f) scrollOffset - oldOffset }, flingConfig = FlingConfig(AndroidFlingDecaySpec(density)) { target -> @@ -108,7 +108,7 @@ private data class PagerState( floor(currentPageFraction) * pageDimen } else { ceil(currentPageFraction) * pageDimen }.coerceIn(-1 * maxPageFraction * pageDimen, 0f) TargetAnimation(newTarget, tween()) }, -
mayojava created this gist
Oct 5, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,117 @@ package dev.efemoney.orchestra.ui import androidx.compose.animation.asDisposableClock import androidx.compose.animation.core.AnimationClockObservable import androidx.compose.animation.core.TargetAnimation import androidx.compose.animation.core.tween import androidx.compose.foundation.animation.AndroidFlingDecaySpec import androidx.compose.foundation.animation.FlingConfig import androidx.compose.foundation.gestures.ScrollableController import androidx.compose.foundation.gestures.scrollable import androidx.compose.foundation.layout.offset import androidx.compose.runtime.* import androidx.compose.ui.Layout import androidx.compose.ui.Modifier import androidx.compose.ui.platform.AnimationClockAmbient import androidx.compose.ui.platform.DensityAmbient import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEachIndexed import androidx.compose.ui.util.fastMap import kotlin.math.ceil import kotlin.math.floor import androidx.compose.ui.gesture.scrollorientationlocking.Orientation import androidx.compose.ui.gesture.scrollorientationlocking.Orientation.Horizontal import androidx.compose.ui.gesture.scrollorientationlocking.Orientation.Vertical @Composable fun Pager( orientation: Orientation, modifier: Modifier = Modifier, children: @Composable () -> Unit = emptyContent() ) { val pagerState = rememberPagerState(orientation) Layout( children, modifier .scrollable(pagerState.orientation, pagerState.scrollController) .scrollOffset(orientation, pagerState.scrollOffset.inDp) ) { measurables, constraints -> val placeables = measurables.fastMap { it.measure(constraints) } val measuredSize = placeables.fold(IntSize.Zero) { currentMax, placeable -> IntSize( width = maxOf(currentMax.width, placeable.width), height = maxOf(currentMax.height, placeable.height) ) } pagerState.pageCount = placeables.size pagerState.pageDimen = if (orientation == Horizontal) measuredSize.width else measuredSize.height layout(measuredSize.width, measuredSize.height) { placeables.fastForEachIndexed { index, placeable -> val pageOffset = pagerState.pageDimen * index val pageDx = if (orientation == Horizontal) pageOffset else 0 val pageDy = if (orientation == Vertical) pageOffset else 0 placeable.placeRelative( pageDx + (measuredSize.width - placeable.width) / 2, pageDy + (measuredSize.height - placeable.height) / 2, ) } } } } fun Modifier.scrollOffset(orientation: Orientation, offset: Dp) = offset( x = if (orientation ==Horizontal) offset else 0.dp, y = if (orientation == Vertical) offset else 0.dp ) @Composable private fun rememberPagerState(orientation: Orientation): PagerState { val density = DensityAmbient.current val clock = AnimationClockAmbient.current.asDisposableClock() return remember(orientation, density, clock) { PagerState(orientation, density, clock) } } @Stable private data class PagerState( val orientation: Orientation, val density: Density, val clock: AnimationClockObservable ) { var scrollOffset by mutableStateOf(0f) var pageDimen by mutableStateOf(0) var pageCount by mutableStateOf(0) val maxPageFraction get() = pageCount - 1f val currentPageFraction get() = scrollOffset / pageDimen val scrollController = ScrollableController( consumeScrollDelta = { scrollDelta -> val oldOffset = scrollOffset scrollOffset = (oldOffset + scrollDelta).coerceIn(maxPageFraction * -pageDimen, 0f) scrollOffset - oldOffset }, flingConfig = FlingConfig(AndroidFlingDecaySpec(density)) { target -> val newTarget = if (target < scrollOffset) { floor(currentPageFraction) * pageDimen } else { ceil(currentPageFraction) * pageDimen }.coerceIn(maxPageFraction * -pageDimen, 0f) TargetAnimation(newTarget, tween()) }, animationClock = clock ) }