Skip to content

Instantly share code, notes, and snippets.

@syarihu
Last active April 19, 2023 07:24
Show Gist options
  • Save syarihu/0ecbf5c1e3cc772a587502f529951c59 to your computer and use it in GitHub Desktop.
Save syarihu/0ecbf5c1e3cc772a587502f529951c59 to your computer and use it in GitHub Desktop.
inline fun <T> LazyGridScope.chunkedItems(
items: List<T>,
chunkSize: Int,
chunkedContentPadding: PaddingValues = PaddingValues(0.dp),
rowSpace: Dp = 0.dp,
noinline key: ((item: List<T>) -> Any)? = null,
noinline span: (LazyGridItemSpanScope.(item: List<T>) -> GridItemSpan)? = null,
noinline contentType: (item: List<T>) -> Any? = { null },
crossinline itemContent: @Composable LazyGridItemScope.(item: T) -> Unit,
) = items(
items = items.chunked(chunkSize),
span = span,
key = key,
contentType = contentType,
) { chunkedItems ->
Row(
Modifier
.fillMaxWidth()
.padding(chunkedContentPadding),
) {
chunkedItems.forEachIndexed { index, item ->
Box(modifier = Modifier.fillMaxWidth().weight(1f)) {
itemContent(item)
}
if (index < chunkedItems.lastIndex || chunkedItems.size < chunkSize) {
Spacer(modifier = Modifier.size(rowSpace))
}
}
val spacerLastIndex = chunkSize - chunkedItems.size - 1
repeat(chunkSize - chunkedItems.size) { index ->
Box(modifier = Modifier.fillMaxWidth().weight(1f))
if (index < spacerLastIndex) {
Spacer(modifier = Modifier.size(rowSpace))
}
}
}
}
inline fun <T> LazyGridScope.chunkedItemsIndexed(
items: List<T>,
chunkSize: Int,
chunkedContentPadding: PaddingValues = PaddingValues(0.dp),
rowSpace: Dp = 0.dp,
noinline key: ((chunkIndex: Int, item: List<T>) -> Any)? = null,
noinline span: (LazyGridItemSpanScope.(chunkIndex: Int, item: List<T>) -> GridItemSpan)? = null,
noinline contentType: (chunkIndex: Int, item: List<T>) -> Any? = { _, _ -> null },
crossinline itemContent: @Composable LazyGridItemScope.(index: Int, item: T) -> Unit,
) {
itemsIndexed(
items = items.chunked(chunkSize),
span = span,
key = key,
contentType = contentType,
) { chunkIndex, chunkedItems ->
Row(
Modifier
.fillMaxWidth()
.padding(chunkedContentPadding),
) {
chunkedItems.forEachIndexed { index, item ->
Box(modifier = Modifier.fillMaxWidth().weight(1f)) {
itemContent(chunkIndex * chunkSize + index, item)
}
if (index < chunkedItems.lastIndex || chunkedItems.size < chunkSize) {
Spacer(modifier = Modifier.size(rowSpace))
}
}
val spacerLastIndex = chunkSize - chunkedItems.size - 1
repeat(chunkSize - chunkedItems.size) { index ->
Box(modifier = Modifier.fillMaxWidth().weight(1f))
if (index < spacerLastIndex) {
Spacer(modifier = Modifier.size(rowSpace))
}
}
}
}
}
private const val GRID_COLUMN_SIZE = 3
@Composable
fun ChunkedItemsSample(
items: List<String> = buildList { repeat(26) { add("item$it") } }
) {
LazyVerticalGrid(
modifier = Modifier.fillMaxSize(),
columns = GridCells.Fixed(count = GRID_COLUMN_SIZE)
) {
item(span = { GridItemSpan(GRID_COLUMN_SIZE) }) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.background(Color.DarkGray),
contentAlignment = Alignment.Center
) {
Text(
text = "Header",
color = Color.White,
)
}
}
chunkedItems(
items = items,
chunkSize = GRID_COLUMN_SIZE,
span = { GridItemSpan(GRID_COLUMN_SIZE) },
rowSpace = 8.dp,
chunkedContentPadding = PaddingValues(top = 8.dp, start = 8.dp, end = 8.dp)
) { item ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.background(color = Color.LightGray)
.padding(8.dp)
) {
Image(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = null
)
Text(text = item)
}
}
item(span = { GridItemSpan(GRID_COLUMN_SIZE) }) { Spacer(modifier = Modifier.size(8.dp)) }
item(span = { GridItemSpan(GRID_COLUMN_SIZE) }) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.background(Color.DarkGray),
contentAlignment = Alignment.Center
) {
Text(
text = "Footer",
color = Color.White,
)
}
}
}
}
@Preview
@Composable
private fun ChunkedItemsSamplePreview() {
ChunkedItemsSample()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment