18

I am trying to display paged items using LazyVerticalGrid. The code I am trying is shown below.

 val categories = repo.categories.collectAsLazyPagingItems()

 LazyVerticalGrid(
    cells = GridCells.Fixed(2),
    modifier = Modifier.padding(8.dp)
 ) {

      items(categories) { category ->
          Box(Modifier.padding(8.dp)) {
              CategoryView(category)
          }
      }

 }

Please note that I have imported androidx.paging.compose.items and androidx.paging.compose.collectAsLazyPagingItems. Also categories is of type LazyPagingItems<Category>.

It works perfectly with LazyColumn and LazyRow but not LazyVerticalGrid. The error I am getting is:

Type mismatch.
Required:
Int
Found:
LazyPagingItems<Category>
Olu Udeh
  • 1,031
  • 1
  • 10
  • 20

4 Answers4

21

I came up with a solution by writing an extension function for LazyGridScope like the one written for LazyListScope in the androidx.paging:paging-compose library.

@ExperimentalFoundationApi
public fun <T: Any> LazyGridScope.items(
    lazyPagingItems: LazyPagingItems<T>,
    itemContent: @Composable LazyItemScope.(value: T?) -> Unit
) {
    items(lazyPagingItems.itemCount) { index ->
        itemContent(lazyPagingItems[index])
    }
}
Mahmudul Hasan Shohag
  • 2,203
  • 1
  • 22
  • 30
Olu Udeh
  • 1,031
  • 1
  • 10
  • 20
  • 1
    Thank you. I wonder how LazyColumn worded for you. For me it complains the stuff on requiring Int. So I have to provide the same extension function for LazyListScope – LXJ Mar 18 '22 at 19:19
  • @LeoXJ you dont. You have the wrong import for it. There are multiple items() functions – SpawnTheTronix Jun 23 '22 at 15:27
9

For me the accepted answer didn't work. Instead of adding extension function I used the following way

val res = viewModel.getFeedResultStream().collectAsLazyPagingItems()

LazyVerticalGrid(columns = GridCells.Fixed(2)){
    items(res.itemCount)
    { index ->
        res[index]?.let {
            FeedItem(it)
        }
    }
}
Fahime Ghasemi
  • 775
  • 9
  • 13
8

copied from androidx.paging:paging-compose

fun <T : Any> LazyGridScope.items(
    items: LazyPagingItems<T>,
    key: ((item: T) -> Any)? = null,
    itemContent: @Composable LazyGridItemScope.(item: T?) -> Unit
) {
    items(
        count = items.itemCount,
        key = if (key == null) null else { index ->
            val item = items.peek(index)
            if (item == null) {
                PagingPlaceholderKey(index)
            } else {
                key(item)
            }
        }
    ) { index ->
        itemContent(items[index])
    }
}

@SuppressLint("BanParcelableUsage")
private data class PagingPlaceholderKey(private val index: Int) : Parcelable {
    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeInt(index)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object {
        @Suppress("unused")
        @JvmField
        val CREATOR: Parcelable.Creator<PagingPlaceholderKey> =
            object : Parcelable.Creator<PagingPlaceholderKey> {
                override fun createFromParcel(parcel: Parcel) =
                    PagingPlaceholderKey(parcel.readInt())

                override fun newArray(size: Int) = arrayOfNulls<PagingPlaceholderKey?>(size)
            }
    }
}
Simsim
  • 121
  • 1
  • 2
5

There is no need to create a extension function. Just use the other version of items function.

val categories = repo.categories.collectAsLazyPagingItems()

 LazyVerticalGrid(
    cells = GridCells.Fixed(2),
    modifier = Modifier.padding(8.dp)
 ) {
      items(
        categories.itemCount
      ) { index ->
          Box(Modifier.padding(8.dp)) {
              CategoryView(categories[index])
          }
      }

 }
Chunhui Deng
  • 111
  • 1
  • 4