Компоненты LazyVerticalGrid и LazyHorizontalGrid обеспечивают отображение элементов в виде сетки. Эти компоненты похожи на списки LazyColumn/LazyRow, только для описания содержимого применяют интерфейс LazyGridScope
LazyHorizontalGrid отображает элементы в горизонтально прокручиваемом контейнере, распределенном по нескольким строкам, и имеет следующие параметры:
@Composable fun LazyHorizontalGrid( rows: GridCells, modifier: Modifier = Modifier, state: LazyGridState = rememberLazyGridState(), contentPadding: PaddingValues = PaddingValues(0.dp), reverseLayout: Boolean = false, horizontalArrangement: Arrangement.Horizontal = if (!reverseLayout) Arrangement.Start else Arrangement.End, verticalArrangement: Arrangement.Vertical = Arrangement.Top, flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), userScrollEnabled: Boolean = true, content: LazyGridScope.() -> Unit ): Unit
rows
: представляет тип GridCells, который описывает количество и размер строк
modifier
: применяемые к контейнеру модификаторы
state
: объект состояния LazyGridState, применяемый для управления состоянием контейнера
contentPadding
: отступы вокруг содержимого
reverseLayout
: при значении true
располагает элементы в обратном порядке
verticalArrangement
: настройки расположения элементов по горизонтали
horizontalArrangement
: выравнивание элементов по вертикали
flingBehavior
: описывает поведение при таком типе прокрутки, когда пользователь быстро перетаскивает что-то и поднимает палец.
Представляет объект FlingBehavior
userScrollEnabled
: указывает, доступна ли прокрутка жестами либо через специальные инструменты управления доступом
content
: устанавливает содержимое контейнера с помощью функции типа LazyGridScope.() -> Unit
.
Для установки содержимого интерфейс LazyGridScope предоставляет несколько функций:
LazyListScope.item()
: для добавления одного элемента
LazyListScope.items()
: для добавления нескольких элементов
LazyListScope.itemsIndexed()
: для добавления нескольких элементов с использованием индексов
Для определения количества и размера ячеек применяется интерфейс GridCells. В частности, он предоставляет следующие методы:
GridCells.Adaptive
: определяет сетку с максимально возможным количеством строк или столбцов при условии, что каждая ячейка имеет как минимум пространство minSize
и все дополнительное пространство распределено равномерно.
GridCells.Исправлено
: определяет сетку с фиксированным количеством строк или столбцов.
GridCells.FixedSize
: определяет сетку с максимально возможным количеством строк или столбцов при условии, что каждая ячейка занимает ровное пространство.
Например, определим простейший грид из текстовых элементов:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val itemsList = (0..12).toList() LazyHorizontalGrid( rows = GridCells.Fixed(3), modifier = Modifier.fillMaxSize() ){ items(itemsList) {item -> Text("Item $item", fontSize = 28.sp,modifier= Modifier.padding(8.dp)) } } } } }
В данном случае для создания грида применяется список itemsList из 13 элементов. С помощью параметра
rows = GridCells.Fixed(3)
определяем три строки. Для заполнения этих строк вызывается функция items()
items(itemsList) {item -> Text("Item $item", fontSize = 28.sp,modifier= Modifier.padding(8.dp)) }
Таким образом, все элементы будут последовательно располагаться в первом столбце, когда последняя строка будет заполнена, создается новый столбец и т.д.
Данный могут более сложными по композиции, и соответственно для их отображения могут использоваться более сложные композиции компонентов:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.background import androidx.compose.ui.graphics.Color import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.lazy.grid.items import androidx.compose.ui.Alignment import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val langs = listOf(Language("Kotlin", 0xff16a085), Language("Java", 0xff2980b9), Language("JavaScript", 0xff8e44ad), Language("Python", 0xff2c3e50), Language("Rust",0xffd35400), Language("C#",0xff27ae60), Language("C++",0xfff39c12), Language("Go",0xff1abc9c)) LazyHorizontalGrid( rows = GridCells.Fixed(2), modifier = Modifier.fillMaxSize(), horizontalArrangement = Arrangement.Center ){ items(langs) {lang -> Column(Modifier.padding(8.dp).size(125.dp), horizontalAlignment = Alignment.CenterHorizontally){ Box(Modifier.size(100.dp).background(Color(lang.hexColor))) Text(lang.name, fontSize = 24.sp,modifier= Modifier.padding(5.dp)) } } } } } } data class Language(val name:String, val hexColor: Long)
Здесь для представления данных применяется класс Language, который хранит название языка программирования и связанный с ним цвет. А список langs хранит набор объектов Language. Для вывода этого списка в грид создается компонент LazyHorizontalGrid с 2-мя столбцами. Внутри каждой ячейки отображаем Box, закрашенный в определенный цвет, и текст с названием языка.
Обратите внимание, что два элемента не поместились на экране смартфона, и для их просмотра надо использовать горизонтальную прокрутку.
LazyVerticalGrid отображает элементы в вертикально прокручиваемом контейнере, распределенном по нескольким столбцам, и имеет следующие параметры:
@Composable fun LazyVerticalGrid( columns: GridCells, modifier: Modifier = Modifier, state: LazyGridState = rememberLazyGridState(), contentPadding: PaddingValues = PaddingValues(0.dp), reverseLayout: Boolean = false, verticalArrangement: Arrangement.Vertical = if (!reverseLayout) Arrangement.Top else Arrangement.Bottom, horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), userScrollEnabled: Boolean = true, content: LazyGridScope.() -> Unit ): Unit
columns
: представляет объект GridCells, который описывает количество и размер столбцов
modifier
: применяемые к контейнеру модификаторы
state
: объект состояния LazyGridState, применяемый для управления состоянием контейнера
contentPadding
: отступы вокруг содержимого
reverseLayout
: при значении true
располагает элементы в обратном порядке
verticalArrangement
: настройки расположения элементов по вертикали
horizontalArrangement
: выравнивание элементов по горизонтали
flingBehavior
: описывает поведение при таком типе прокрутки, когда пользователь быстро перетаскивает что-то и поднимает палец.
Представляет объект FlingBehavior
userScrollEnabled
: указывает, доступна ли прокрутка жестами либо через специальные инструменты управления доступом
content
: устанавливает содержимое контейнера с помощью функции типа LazyGridScope.() -> Unit
.
LazyVerticalGrid во многом аналогичен LazyHorizontalGrid
. Так, перепишем предыдущий пример с использованием LazyVerticalGrid:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.background import androidx.compose.ui.graphics.Color import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.lazy.grid.items import androidx.compose.ui.Alignment import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val langs = listOf(Language("Kotlin", 0xff16a085), Language("Java", 0xff2980b9), Language("JavaScript", 0xff8e44ad), Language("Python", 0xff2c3e50), Language("Rust",0xffd35400), Language("C#",0xff27ae60), Language("C++",0xfff39c12), Language("Go",0xff1abc9c)) LazyVerticalGrid( columns = GridCells.Fixed(2), modifier = Modifier.fillMaxSize(), horizontalArrangement = Arrangement.Center ){ items(langs) {lang -> Column(Modifier.padding(8.dp), horizontalAlignment = Alignment.CenterHorizontally){ Box(Modifier.size(100.dp).background(Color(lang.hexColor))) Text(lang.name, fontSize = 24.sp,modifier= Modifier.padding(5.dp)) } } } } } } data class Language(val name:String, val hexColor: Long)
Здесь практически то же самое, только в LazyVerticalGrid вместо строк здесь задаем 2 столбца. Соответственно сначала элементы заполняются 2 стобца первой строки. Если после этого еще есть элементы, то создается вторая строка и так далее. А чтобы просмотреть те элементы, которые не поместились на экране, надо использовать вертикальную прокрутку.
В примерах выше применялось точное количество строк/столбцов. Для этого использовался метод GridCells.Fixed()
, в который передавалось количество строк/столбцов. Теперь рассмотрим другие возможности установки размеров.
Так, метод GridCells.Adaptive(). Он определяет сетку с максимально возможным количеством строк или столбцов при условии, что каждая ячейка имеет как минимум размер minSize и все дополнительное пространство распределено равномерно. Значение minSize,
которе указывает на минимаьную высоту строки или минимальную ширину столбца, передается в метод GridCells.Adaptive() в качестве единственного параметра. Например:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.background import androidx.compose.ui.graphics.Color import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.lazy.grid.items import androidx.compose.ui.Alignment import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val langs = listOf(Language("Kotlin", 0xff16a085), Language("Java", 0xff2980b9), Language("JavaScript", 0xff8e44ad), Language("Python", 0xff2c3e50), Language("Rust",0xffd35400), Language("C#",0xff27ae60), Language("C++",0xfff39c12), Language("Go",0xff1abc9c)) LazyVerticalGrid( columns = GridCells.Adaptive(minSize=120.dp), modifier = Modifier.fillMaxSize(), horizontalArrangement = Arrangement.Center ){ items(langs) {lang -> Column(Modifier.padding(7.dp), horizontalAlignment = Alignment.CenterHorizontally){ Box(Modifier.size(100.dp).background(Color(lang.hexColor))) Text(lang.name, fontSize = 24.sp) } } } } } } data class Language(val name:String, val hexColor: Long)
В данном случае создается вертикальный грид, в котором минимальная ширина каждой ячейки равна 120 пикселей:
columns = GridCells.Adaptive(minSize=120.dp)
Минимальную ширину в данном случае я определил на основе содержимого ячейки. В итоге при вертикальной ориентации на моем устройстве будет создано 3 столбца
Тогда как при горизонтальной ориентации будет создаваться аж 5 столбцов
Данный подход может показать лучше, чем установка фиксированного количества строк/столбцов, поскольку экранное пространство устройства расходуется более экономично.
Еще один метод GridCells.FixedSize() позволяет задать точный размер ячейки (ширину столбцов или высоту строк). В этом случае создается максимально возможное количество строк или столбцов при условии, что каждая ячейка имеет указанный размер. Значение размера передается в метод GridCells.FixedSize() в качестве единственного параметра. Например:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.background import androidx.compose.ui.graphics.Color import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.lazy.grid.items import androidx.compose.ui.Alignment import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val langs = listOf(Language("Kotlin", 0xff16a085), Language("Java", 0xff2980b9), Language("JavaScript", 0xff8e44ad), Language("Python", 0xff2c3e50), Language("Rust",0xffd35400), Language("C#",0xff27ae60), Language("C++",0xfff39c12), Language("Go",0xff1abc9c)) LazyVerticalGrid( columns = GridCells.FixedSize(size=140.dp), modifier = Modifier.fillMaxSize(), horizontalArrangement = Arrangement.Center ){ items(langs) {lang -> Column(Modifier.padding(7.dp), horizontalAlignment = Alignment.CenterHorizontally){ Box(Modifier.size(100.dp).background(Color(lang.hexColor))) Text(lang.name, fontSize = 24.sp) } } } } } } data class Language(val name:String, val hexColor: Long)
В данном случае создается вертикальный грид, в котором ширина каждой ячейки должна быть равна 140 пикселей:
columns = GridCells.FixedSize(size=140.dp)
В итоге при вертикальной ориентации на моем устройстве будет создано 2 столбца
Тогда как при горизонтальной ориентации будет создаваться 4 столбца