Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create GridView using Jetpack Compose

How to create Gridview in Jetpack compose without using recycler view or android.widget.gridview ?

like image 945
Gopi S Avatar asked Oct 28 '19 18:10

Gopi S


People also ask

How do you make a scrollable column in jetpack compose?

We can make the Column scrollable by using the verticalScroll() modifier.

What is LazyColumn?

A LazyColumn is a vertically scrolling list that only composes and lays out the currently visible items. It's similar to a Recyclerview in the classic Android View system.

What is scaffold in compose?

Scaffold provides slots for a top app bar or a bottom app bar. The placement of the composables is handled internally. You can use the topBar slot and a TopAppBar : Scaffold( topBar = {

What is jetpack compose?

Jetpack Compose is Android's modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.


4 Answers

With 1.x.y the LazyVerticalGrid composable provides experimental support for displaying items in a grid.

val numbers = (0..20).toList()

LazyVerticalGrid(
    cells = GridCells.Fixed(4)
) {
    items(numbers.size) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            Text(text = "Number")
            Text(text = "  $it",)
        }
    }
}

The cells = GridCells.Fixed(4) would mean that there are 4 columns 1/4 of the parent wide.

enter image description here

val numbers = (0..20).toList()

LazyVerticalGrid(
    cells = GridCells.Adaptive(minSize = 64.dp)
) {
    items(numbers) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            Text(text = "Number")
            Text(text = "  $it",)
        }
    }
}

cells = GridCells.Adaptive(minSize = 64.dp) would mean that there will be as many columns as possible and every column will be at least 64.dp and all the columns will have equal width.

enter image description here

like image 181
Gabriele Mariotti Avatar answered Oct 20 '22 20:10

Gabriele Mariotti


UPD: Compose version 1.0.0-alpha09 introduces standard component:

LazyVerticalGrid

Yet another solution based on LazyColumnFor (Jetpack Compose version 1.0.0-alpha04)

@Composable
fun <T> LazyGridFor(
    items: List<T>,
    rowSize: Int = 1,
    itemContent: @Composable BoxScope.(T) -> Unit,
) {
    val rows = items.chunked(rowSize)
    LazyColumnFor(rows) { row ->
        Row(Modifier.fillParentMaxWidth()) {
            for ((index, item) in row.withIndex()) {
                Box(Modifier.fillMaxWidth(1f / (rowSize - index))) {
                    itemContent(item)
                }
            }
        }
    }
}
    
@Preview("LazyGridFor: example")
@Composable()
fun LazyGridForPreview() {
    val data = (1..100).map(Integer::toString)
    LazyGridFor(data, 3) { item ->
        Text(item)
    }
}
like image 45
Pavel Marchenko Avatar answered Oct 20 '22 22:10

Pavel Marchenko


As @Pavel Marchenko mentioned, LazyVerticalGrid is added from version 1.0.0-alpha09

Here is a quick example:

    LazyVerticalGrid(
        cells = GridCells.Adaptive(96.dp),
        contentPadding = PaddingValues(16.dp),
    ) {
        items(bookList) { book ->
            Image(book.cover, modifier = Modifier.padding(8.dp))
        }
    }
like image 37
AnT Avatar answered Oct 20 '22 22:10

AnT


I have created a adaptative grid layout:

Preveiw

Jetpack compose adaptative grid layout landscape|tablette

Jetpack compose adaptative grid layout

Code

LazyColumn(modifier = modifier) {
            ...
            val numberOfItemsByRow = LocalConfiguration.current.screenWidthDp / 200 // you can replace 200 by the minimum size you want your cells to have.

            items(items = trendingGameList.chunked(numberOfItemsByRow)) { rowItems ->
                Row(
                    horizontalArrangement = Arrangement.spacedBy(14.dp),
                    modifier = Modifier.padding(horizontal = 16.dp),
                ) {
                    for (game in rowItems) {
                        GameCard(game = game, onClick = { }, modifier = Modifier.weight(1F))
                    }
                }
                Spacer(Modifier.height(14.dp))
            }
            ...
        }

The full code is here.

I decided to implement my own adaptative grid layout because the existing LazyVerticalGrid is experimental and can be removed in the future, and to use it you have to annotate the compostables that uses it with @ExperimentalFoundationApi recursively:

@ExperimentalFoundationApi 
@Composable
fun A {
    LazyVerticalGrid {
        ...
    }
}

@ExperimentalFoundationApi 
@Composable
fun B {
 A {..}
}

@ExperimentalFoundationApi 
@Composable
fun C {
 B {..}
}
...

OR use the @OptIn(ExperimentalFoundationApi::class) which require the -Xopt-in=kotlin.RequiresOptIn compiler argument.

like image 7
sitatech Avatar answered Oct 20 '22 22:10

sitatech