LazyLayoutItemProvider


Provides all the needed info about the items which could be later composed and displayed as children or LazyLayout. The number of virtual items is limited by LazyLayoutItemProvider.itemCount.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.layout.LazyLayout
import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.dp

val items = remember { (0..100).toList().map { it.toString() } }

// Create an item provider
val itemProvider = remember {
    {
        object : LazyLayoutItemProvider {
            override val itemCount: Int
                get() = 100

            @Composable
            override fun Item(index: Int, key: Any) {
                Box(
                    modifier =
                        Modifier.width(100.dp)
                            .height(100.dp)
                            .background(color = if (index % 2 == 0) Color.Red else Color.Green)
                ) {
                    Text(text = items[index])
                }
            }
        }
    }
}

LazyLayout(modifier = Modifier.size(500.dp), itemProvider = itemProvider) { constraints ->
    // plug the measure policy, this is how we create and layout items.
    val placeablesCache = mutableListOf<Pair<Placeable, Int>>()
    fun Placeable.mainAxisSize() = width
    fun Placeable.crossAxisSize() = height

    val childConstraints =
        Constraints(maxWidth = Constraints.Infinity, maxHeight = constraints.maxHeight)

    var currentItemIndex = 0
    var crossAxisSize = 0
    var mainAxisSize = 0

    // measure items until we either fill in the space or run out of items.
    while (mainAxisSize < constraints.maxWidth && currentItemIndex < items.size) {
        val itemPlaceables = compose(currentItemIndex).map { it.measure(childConstraints) }
        for (item in itemPlaceables) {
            // save placeable to be placed later.
            placeablesCache.add(item to mainAxisSize)

            mainAxisSize += item.mainAxisSize() // item size contributes to main axis size
            // cross axis size will the size of tallest/widest item
            crossAxisSize = maxOf(crossAxisSize, item.crossAxisSize())
        }
        currentItemIndex++
    }

    val layoutWidth = minOf(mainAxisSize, constraints.maxHeight)
    val layoutHeight = crossAxisSize

    layout(layoutWidth, layoutHeight) {
        // since this is a linear list all items are placed on the same cross-axis position
        for ((placeable, position) in placeablesCache) {
            placeable.place(position, 0)
        }
    }
}

Summary

Public functions

Unit
@Composable
Item(index: @IntRange(from = 0) Int, key: Any)

The item for the given index and key.

Cmn
open Any?
getContentType(index: @IntRange(from = 0) Int)

Returns the content type for the item on this index.

Cmn
open Int
getIndex(key: Any)

Get index for given key.

Cmn
open Any
getKey(index: @IntRange(from = 0) Int)

Returns the key for the item on this index.

Cmn

Public properties

Int

The total number of items in the lazy layout (visible or not).

Cmn

Public functions

Item

@Composable
fun Item(index: @IntRange(from = 0) Int, key: Any): Unit

The item for the given index and key.

getContentType

open fun getContentType(index: @IntRange(from = 0) Int): Any?

Returns the content type for the item on this index. It is used to improve the item compositions reusing efficiency. Note that null is a valid type and items of such type will be considered compatible.

getIndex

open fun getIndex(key: Any): Int

Get index for given key. The index is not guaranteed to be known for all keys in layout for optimization purposes, but must be present for elements in current viewport. If the key is not present in the layout or is not known, return -1.

getKey

open fun getKey(index: @IntRange(from = 0) Int): Any

Returns the key for the item on this index.

See also
getDefaultLazyLayoutKey

which you can use if the user didn't provide a key.

Public properties

itemCount

val itemCountInt

The total number of items in the lazy layout (visible or not).