Skip to content

Instantly share code, notes, and snippets.

@cp-hardik-p
Last active January 15, 2024 12:40
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cp-hardik-p/d460776476906f165284ca1cb05fb073 to your computer and use it in GitHub Desktop.
Save cp-hardik-p/d460776476906f165284ca1cb05fb073 to your computer and use it in GitHub Desktop.
private const val SCROLL_DX = 24f
private const val REQUIRED_CARD_COUNT = 8
private class AutoScrollItem<T>(
val id: String = UUID.randomUUID().toString(),
val data: T
)
@Composable
fun <T : Any> AutoScrollingLazyRow(
list: List<T>,
modifier: Modifier = Modifier,
itemContent: @Composable (item: T) -> Unit,
) {
val lazyListState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
var items by remember { mutableStateOf(list.mapAutoScrollItem()) }
LazyRow(
state = lazyListState,
modifier = modifier,
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
itemsIndexed(
items, key = { _, item -> item.id }
) { index, item ->
itemContent(item = item.data)
if (index == items.lastIndex) {
val currentList = items
val firstVisibleItemIndex = lazyListState.firstVisibleItemIndex
val secondPart = currentList.subList(0, firstVisibleItemIndex)
val firstPart =
currentList.subList(firstVisibleItemIndex, currentList.size)
LaunchedEffect(key1 = Unit) {
coroutineScope.launch {
lazyListState.scrollToItem(
0,
maxOf(0, lazyListState.firstVisibleItemScrollOffset - SCROLL_DX.toInt())
)
}
}
items = (firstPart + secondPart)
}
}
}
LaunchedEffect(key1 = Unit) {
coroutineScope.launch {
while (true) {
lazyListState.autoScroll()
}
}
}
}
private fun <T : Any> List<T>.mapAutoScrollItem(): List<AutoScrollItem<T>> {
val newList = this.map { AutoScrollItem(data = it) }.toMutableList()
var index = 0
if (this.size < REQUIRED_CARD_COUNT) {
while (newList.size != REQUIRED_CARD_COUNT) {
if (index > this.size - 1) {
index = 0
}
newList.add(AutoScrollItem(data = this[index]))
index++
}
}
return newList
}
suspend fun ScrollableState.autoScroll(
animationSpec: AnimationSpec<Float> = tween(durationMillis = 800, easing = LinearEasing)
) {
var previousValue = 0f
scroll(MutatePriority.PreventUserInput) {
animate(0f, SCROLL_DX, animationSpec = animationSpec) { currentValue, _ ->
previousValue += scrollBy(currentValue - previousValue)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment