timeline : improve jumpTo precision (introducing animateScrollToItemCenter)

This commit is contained in:
ganfra 2024-10-03 12:49:24 +02:00
parent 88e01e7c2e
commit adc03c9676
14 changed files with 102 additions and 86 deletions

View file

@ -7,6 +7,8 @@
package io.element.android.libraries.designsystem.utils
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.lazy.LazyListLayoutInfo
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
@ -35,3 +37,38 @@ fun LazyListState.isScrollingUp(): Boolean {
}
}.value
}
suspend fun LazyListState.animateScrollToItemCenter(index: Int) {
fun LazyListLayoutInfo.containerSize(): Int {
return if (orientation == Orientation.Vertical) {
viewportSize.height
} else {
viewportSize.width
} - beforeContentPadding - afterContentPadding
}
fun LazyListLayoutInfo.resolveItemOffsetToCenter(index: Int): Int? {
val itemInfo = visibleItemsInfo.firstOrNull { it.index == index } ?: return null
val containerSize = containerSize()
val itemSize = itemInfo.size
return if (itemSize > containerSize) {
itemSize - containerSize / 2
} else {
-(containerSize() - itemInfo.size) / 2
}
}
// await for the first layout.
scroll { }
layoutInfo.resolveItemOffsetToCenter(index)?.let { offset ->
// Item is already visible, just scroll to center.
animateScrollToItem(index, offset)
return
}
// Item is not visible, jump to it...
scrollToItem(index)
// and then adjust according to the actual item size.
layoutInfo.resolveItemOffsetToCenter(index)?.let { offset ->
animateScrollToItem(index, offset)
}
}

View file

@ -26,5 +26,4 @@ sealed interface VirtualTimelineItem {
) : VirtualTimelineItem
data object TypingNotification : VirtualTimelineItem
}

View file

@ -16,7 +16,6 @@ import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTime
* This post processor is responsible for adding a typing notification item to the timeline items when the timeline is in live mode.
*/
class TypingNotificationPostProcessor(private val mode: Timeline.Mode) {
fun process(items: List<MatrixTimelineItem>): List<MatrixTimelineItem> {
return if (mode == Timeline.Mode.LIVE) {
buildList {