Лабораторно упражнение 9

Lists and grids

Много приложения трябва да показват колекции от елементи. Този документ обяснява как може ефективно да направи това в Jetpack Compose.

Ако знаете, че вашият случай на употреба не изисква превъртане, може да използвайте Column или Row и излъчвайте съдържанието на всеки елемент чрез Итериране на списък по следния начин:

@Composable
fun MessageList(messages: List<Message>) {
    Column {
        messages.forEach { message ->
            MessageRow(message)
        }
    }
}

Можем да направим превъртане с помощта на модификатора verticalScroll()

Мързеливи списъци

Ако трябва да покажете голям брой елементи (или списък с неизвестна дължина), Използването на оформление Column може да причини проблеми с производителността, тъй като всички елементи ще бъдат съставени и подредени, независимо дали са видими или не.

Compose предоставя набор от компоненти, които композират и подреждат само елементи, които се виждат в прозореца за изглед на компонента. Тези компоненти включват LazyColumn, LazyRow, LazyVerticalGrid, LazyHorizontalGrid

Както подсказва името, разликата между тях е ориентацията, в която те подреждат своите елементи и превъртат.

Компонентите на Lazy са различни от повечето оформления в Compose. Вместо приемане на параметър на блок с елементи на потребителския интерфейс, което позволява на приложенията директно да излъчват Composable елементи, компонентите на Lazy осигуряват LazyListScope блок. Този LazyListScope блок предлага DSL (специфичен за домейна език), който позволява на приложенията да описват съдържанието на елемента. След това мързеливият компонент е отговорен за добавянето на съдържанието на всеки елемент като се изисква от оформлението и позицията на превъртане.

DSL на LazyListScope предоставя редица функции за описване на елементи в оформлението. В най-основния случай item() добавя един елемент, а items(Int) добавя множество елементи:

LazyColumn {
    // Add a single item
    item {
        Text(text = "First item")
    }

    // Add 5 items
    items(5) { index ->
        Text(text = "Item: $index")
    }

    // Add another single item
    item {
        Text(text = "Last item")
    }
}

Има и редица функции за разширение, които ви позволяват да добавяте колекции от елементи, като например списък. Тези разширения ни позволяват лесно да мигрираме нашия пример за колона отгоре:

LazyColumn {
    items(messages) { message ->
        MessageRow(message)
    }
}

Съществува и вариант на функцията за разширение items(), наречена itemsIndexed(), която предоставя индекса.

Lazy grids

Компонентите LazyVerticalGrid и LazyHorizontalGrid осигуряват поддръжка за показване на елементи в мрежа. Мързелива вертикална решетка ще показва елементите си във вертикално превъртащ се контейнер, разпръснат в множество колони, докато мързеливите хоризонтални решетки ще имат същото поведение на хоризонталната ос.

Мрежите имат същите мощни API възможности като списъците и също така използват много подобен DSL - LazyGridScope.() за описание на съдържанието.

Параметърът колони в LazyVerticalGrid и параметърът редове в LazyHorizontalGrid контролират как клетките се формират в колони или редове. Следният пример показва елементи в мрежа, като използва GridCells.Adaptive, за да настрои всяка колона да бъде поне 128.dp широка:

LazyVerticalGrid(
    columns = GridCells.Adaptive(minSize = 128.dp)
) {
    items(photos) { photo ->
        PhotoItem(photo)
    }
}

LazyVerticalGrid ви позволява да зададете ширина за елементите и след това мрежата ще се побере във възможно най-много колони. Всяка оставаща ширина се разпределя по равно между колоните, след като се изчисли броят на колоните. Този адаптивен начин за оразмеряване е особено полезен за показване на набори от елементи на различни размери на екрана.

Ако знаете точния брой колони, които да се използват, можете вместо това да предоставите екземпляр на GridCells.Fixed, съдържащ броя на необходимите колони.

Ако вашият дизайн изисква само определени елементи да имат нестандартни размери, можете да използвате поддръжката на мрежата за предоставяне на персонализирани обхвати на колони за елементи. Посочете обхвата на колоната с параметъра за обхват на методите за елемент и елементи на LazyGridScope DSL. maxLineSpan, една от стойностите на обхвата на обхвата, е особено полезна, когато използвате адаптивно оразмеряване, тъй като броят на колоните не е фиксиран. Този пример показва как да предоставите пълен диапазон от редове:

LazyVerticalGrid(
    columns = GridCells.Adaptive(minSize = 30.dp)
) {
    item(span = {
        // LazyGridItemSpanScope:
        // maxLineSpan
        GridItemSpan(maxLineSpan)
    }) {
        CategoryCard("Fruits")
    }
    // ...
}