Kefas
07/27/2021, 2:08 AManimateScrollBy can be cancelled if I scroll the lazy column at the same time, and then the entire LaunchedEffect will be cancelled.
val scrollState = rememberLazyListState()
LaunchedEffect(Unit) {
while (true) {
delay(1000L)
scrollState.animateScrollBy(100f)
}
}Kefas
07/27/2021, 2:10 AMval scrollState = rememberLazyListState()
var randomNumber by remember { mutableStateOf(0) }
LaunchedEffect(Unit) {
while (true) {
delay(1000L)
randomNumber = Random.nextInt()
}
}
LaunchedEffect(randomNumber) {
scrollState.animateScrollBy(100f)
}Luis
07/27/2021, 2:13 AMLuis
07/27/2021, 2:14 AMKefas
07/27/2021, 2:19 AMscrollState is not changed after scrolling, so it won't trigger the LaunchedEffect again.
val scrollState = rememberLazyListState()
LaunchedEffect(scrollState) {
delay(1000L)
scrollState.animateScrollBy(100f)
}Luis
07/27/2021, 2:33 AMisScrollInProgress property that you can use to trigger itLuis
07/27/2021, 2:33 AMval scrollState = rememberLazyListState()
LaunchedEffect(scrollState.isScrollInProgress) {
if (scrollState.isScrollInProgress) return
delay(1000L)
scrollState.animateScrollBy(100f)
}Albert Chang
07/27/2021, 3:16 AMisScrollInProgress returns true for programmatical scroll as well so I don't think it will work.
Simply catching the CancellationException should be enough:
LaunchedEffect(scrollState) {
while (true) {
delay(1000L)
runCatching { scrollState.animateScrollBy(100f) }
}
}Kefas
07/27/2021, 3:19 AManimateScrollBy will change the isScrollInProgress state into true. I can remove the if (scrollState.isScrollInProgress) return statement, but the delay will be run twice before it's actually scrollingLuis
07/27/2021, 3:58 AMLuis
07/27/2021, 3:59 AMAlbert Chang
07/27/2021, 4:03 AManimateScrollBy is a suspend fun. It'll be canceled when the coroutine scope is canceled.Luis
07/27/2021, 4:09 AMKefas
07/27/2021, 4:15 AMCancellationException which will break the coroutine cancellations.
I'll try to cancel the launched effect when animateScrollBy is still running
https://twitter.com/Zhuinden/status/1389063911702470656Kefas
07/27/2021, 5:15 AMrunCatching on a coroutine block, because the code inside LaunchedEffect will still run even after it's cancelled.
https://gist.github.com/kefasjwiryadi/6c042a6874598ddee88e476ea4523793Albert Chang
07/27/2021, 5:23 AMLaunchedEffect(scrollState) {
while (isActive) {
delay(1000L)
runCatching { scrollState.animateScrollBy(100f) }
}
}Kefas
07/27/2021, 7:32 AMlaunch get cancelled, the parent's (LaunchedEffect) scope doesn't get cancelled.
LaunchedEffect(scrollState) {
while (true) {
delay(1000L)
launch {
scrollState.animateScrollBy(100f)
}
}
}Luis
07/27/2021, 7:37 AMKefas
07/27/2021, 7:42 AMAlbert Chang
07/27/2021, 8:09 AMKefas
07/27/2021, 8:17 AMlaunchmatvei
07/27/2021, 1:25 PMscrollState implements ScrollableState interface, which supports priority based scroll. It's not available out of the box in animateScrollTo , since disrupting and preventing user input is not something that should be easily accessible from the API design perspective. But it's doable if you really want it.
What you are looking for is suspend fun ScrollableState::scroll(priority:MutatePriority)
where you can choose the right priority and prevent user input and implement your own animation like so: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]undation/gestures/ScrollExtensions.kt;l=35?q=ScrollExtensionsKefas
07/27/2021, 2:14 PM