Shakil Karim
01/22/2021, 6:32 PMVadim
01/22/2021, 10:54 PMFlingConfig
is meant for snapping in Compose, and there's flingConfig in LazyListState
that's used by LazyRow. So we can slightly modify rememberLazyListState
to use custom filngConfig:
@Composable
fun rememberFlingLazyListState(
initialFirstVisibleItemIndex: Int = 0,
initialFirstVisibleItemScrollOffset: Int = 0,
interactionState: InteractionState? = null,
config: FlingConfig = defaultFlingConfig()
): LazyListState {
val clock = AmbientAnimationClock.current.asDisposableClock()
// Avoid creating a new instance every invocation
val saver = remember(config, clock, interactionState) {
LazyListState.Saver(config, clock, interactionState)
}
return rememberSavedInstanceState(config, clock, interactionState, saver = saver) {
LazyListState(
initialFirstVisibleItemIndex,
initialFirstVisibleItemScrollOffset,
interactionState,
config,
clock
)
}
}
so it can be used in LazyRow like this:
val badgeListScroll = rememberFlingLazyListState(
config = FlingConfig(
anchors = pageOffsetList, // list of X-coordinates which will be snapped at while scrolling
animationSpec = TweenSpec(),
decayAnimation = FloatExponentialDecaySpec(frictionMultiplier = 1f)
)
)
LazyRow(
modifier = Modifier.fillMaxWidth(),
state = badgeListScroll
) {
itemsIndexed(badgeList) { index, item -> MyBadge(item) }
}
The problem here is to choose correct value for decayAnimation
. FloatExponentialDecaySpec
doesn't allow to set the end coordinate of animation so, after user swipes, scrolling just stops at a 'random' place (depending only on velocity of swipe gesture).
Couple of alphas ago, there wasn't any decay
in FlingConfig
and snapping worked almost fine with similar config...Doris Liu
01/23/2021, 1:53 AMFlingConfig
in your snippet should give you the snapping behavior. If not, please file a bug. 🙂
decayAnimation
describes what the natural slow-down should look like. It is also used to calculate where the natural target point is, in order to choose a snapping target from the given list of anchors
. If/when you have anchors
defined, the animationSpec
is used for the snapping animation. I would suggest having a spring animation for the snapping (instead of tween) to maintain continuity in velocity. If you need a "snappier" animation, you could consider increasing the spring stiffness.Vadim
01/23/2021, 9:23 AMDoris Liu
01/23/2021, 7:12 PMLazyRow
you never want it to come to a stop in-between two items after a gesture (be it panning or flinging). That makes sense. Thanks for clarifying.👍 Looks like that work is already tracked here: https://issuetracker.google.com/issues/166590434 Please feel free to cc yourself to get updates from the work, and/or add additional clarification/request in the tracker. 🙂