Skip to content

Instantly share code, notes, and snippets.

@DantheCodingGui
Created June 7, 2023 12:53
Show Gist options
  • Select an option

  • Save DantheCodingGui/e660e987685b11d2e94af3e94d76797c to your computer and use it in GitHub Desktop.

Select an option

Save DantheCodingGui/e660e987685b11d2e94af3e94d76797c to your computer and use it in GitHub Desktop.
@Composable
fun IndexedLazyColumn(
modifier: Modifier = Modifier,
state: IndexedLazyListState = rememberIndexedLazyListState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
reverseLayout: Boolean = false,
verticalArrangement: Arrangement.Vertical = if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
userScrollEnabled: Boolean = true,
content: IndexedLazyListScope.() -> Unit
) {
LazyColumn(
modifier = modifier,
state = state.listState,
contentPadding = contentPadding,
reverseLayout = reverseLayout,
verticalArrangement = verticalArrangement,
horizontalAlignment = horizontalAlignment,
flingBehavior = flingBehavior,
userScrollEnabled = userScrollEnabled,
) {
IndexedLazyListScope(this, state).content()
}
}
@Composable
fun rememberIndexedLazyListState(
listState: LazyListState = rememberLazyListState(),
): IndexedLazyListState {
return remember { IndexedLazyListState(listState) }
}
@Stable
class IndexedLazyListState internal constructor(
val listState: LazyListState,
) {
val itemIndexMapping = mutableStateMapOf<Any, Int>()
internal fun linkKeyToIndex(key: Any, index: Int) {
itemIndexMapping[key] = index
}
}
@Stable
class IndexedLazyListScope(
private val lazyListScope: LazyListScope,
private val state: IndexedLazyListState,
): LazyListScope {
private var currentItemLayoutIndex = 0
override fun item(key: Any?, contentType: Any?, content: @Composable LazyItemScope.() -> Unit) {
lazyListScope.item(key, contentType, content)
if (key != null)
state.linkKeyToIndex(key, currentItemLayoutIndex)
currentItemLayoutIndex++
}
@Deprecated("Use the non deprecated overload", level = DeprecationLevel.HIDDEN)
override fun item(key: Any?, content: @Composable LazyItemScope.() -> Unit) {
item(key, null, content)
}
override fun items(
count: Int,
key: ((index: Int) -> Any)?,
contentType: (index: Int) -> Any?,
itemContent: @Composable LazyItemScope.(index: Int) -> Unit
) {
lazyListScope.items(count, key, contentType, itemContent)
repeat(count) { i ->
val resolvedKey = key?.invoke(i)
if (resolvedKey != null)
state.linkKeyToIndex(resolvedKey, currentItemLayoutIndex)
currentItemLayoutIndex++
}
}
@Deprecated("Use the non deprecated overload", level = DeprecationLevel.HIDDEN)
override fun items(
count: Int,
key: ((index: Int) -> Any)?,
itemContent: @Composable LazyItemScope.(index: Int) -> Unit
) {
items(count, key, { null }, itemContent)
}
@ExperimentalFoundationApi
override fun stickyHeader(key: Any?, contentType: Any?, content: @Composable LazyItemScope.() -> Unit) {
lazyListScope.stickyHeader(key, contentType, content)
if (key != null)
state.linkKeyToIndex(key, currentItemLayoutIndex)
currentItemLayoutIndex++
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment