Flow-контейнеры (FlowRow и FlowColumn) предназначены для потокового размещения содержимого, когда содержимое автоматические помещается на следующую строку или столбец, если в текущей строке/столбце место заканчилось.
FlowRow располагает элементы слева направо при левосторонней ориентации или справа налево при правосторонней ориентации, а когда заканчивается место, переходит к следующей строке и продолжает заполнять компоненты, пока они не закончатся. Этот компонент имеет следующие параметры:
@Composable @ExperimentalLayoutApi fun FlowRow( modifier: Modifier = Modifier, horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, verticalArrangement: Arrangement.Vertical = Arrangement.Top, maxItemsInEachRow: Int = Int.MAX_VALUE, maxLines: Int = Int.MAX_VALUE, overflow: FlowRowOverflow = FlowRowOverflow.Clip, content: @Composable FlowRowScope.() -> Unit ): Unit
modifier
: применяемые к компоненту функции модификатора.
horizontalArrangement
: расположение вложенных компонентов по горизонтали.
verticalArrangement
: расположение вложенных компонентов по вертикали.
maxItemsInEachRow
: максимальное количество элементов в строке
maxLines
: максимальное количество строк
overflow
: принцип переноса элементов
content
: содержимое контейнера
Простейший пример FlowRow:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent @OptIn(ExperimentalLayoutApi::class) { val rects = listOf( Rect(50f,0xff16a085), Rect(100f,0xff8e44ad), Rect(75f,0xff2980b9), Rect(125f,0xff2c3e50), Rect(100f,0xfff39c12), Rect(75f,0xff27ae60), Rect(50f,0xffd35400), Rect(110f,0xfff6b93b), Rect(100f,0xff0a3d62), Rect(75f,0xffb71540) ) FlowRow(Modifier.fillMaxSize(), maxItemsInEachRow = 4){ rects.forEach({rect -> Box(Modifier.size(Dp(rect.width), 100.dp).padding(5.dp).background(Color(rect.hexColor))) }) } } } } data class Rect(val width: Float, val hexColor: Long)
Здесь для представления данных используется класс Rect, который представляет условный прямоугольник и принимает через конструктор ширину прямоугольника и его цвет в виде числа.
При вызове метода setContent() определяется список rects из объектов Rect, и затем из них создается компонент Box, которые помещаются в FlowRow:
FlowRow(Modifier.fillMaxSize(), maxItemsInEachRow = 4){ rects.forEach({rect -> Box(Modifier.size(Dp(rect.width), 100.dp).padding(5.dp).background(Color(rect.hexColor))) }) }
С помощью параметра maxItemsInEachRow = 4
указываем, что строка будет иметь не более 4 элементов:
Стоит отметить, что FlowRow на момент написания текущей статьи находится в экспериментальном режиме, поэтому перед компонентом, который использует FlowRow указывается аннотация
@OptIn(ExperimentalLayoutApi::class)
FlowColumn располагает элементы сверху вниз, а когда в столбце заканчивается место, переходит к следующему столбцу и продолжает размещать элементы, пока они не закончатся. Этот компонент имеет следующие параметры:
@Composable @ExperimentalLayoutApi fun FlowColumn( modifier: Modifier = Modifier, verticalArrangement: Arrangement.Vertical = Arrangement.Top, horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, maxItemsInEachColumn: Int = Int.MAX_VALUE, maxLines: Int = Int.MAX_VALUE, overflow: FlowColumnOverflow = FlowColumnOverflow.Clip, content: @Composable FlowColumnScope.() -> Unit ): Unit
modifier
: применяемые к компоненту функции модификатора.
horizontalArrangement
: расположение вложенных компонентов по горизонтали.
verticalArrangement
: расположение вложенных компонентов по вертикали.
maxItemsInEachColumn
: максимальное количество элементов в столбце
maxLines
: максимальное количество строк
overflow
: принцип переноса элементов
content
: содержимое контейнера
Для демонстрации FlowColumn рассмотрим следующий пример:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowColumn import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent @OptIn(ExperimentalLayoutApi::class) { val rects = listOf( Rect(50f,0xff16a085), Rect(100f,0xff8e44ad), Rect(75f,0xff2980b9), Rect(125f,0xff2c3e50), Rect(100f,0xfff39c12), Rect(75f,0xff27ae60), Rect(50f,0xffd35400), Rect(110f,0xfff6b93b), Rect(100f,0xff0a3d62), Rect(75f,0xffb71540) ) FlowColumn(Modifier.fillMaxSize(), maxItemsInEachColumn = 4){ rects.forEach({rect -> Box(Modifier.size(100.dp, Dp(rect.height)).padding(5.dp).background(Color(rect.hexColor))) }) } } } } data class Rect(val height: Float, val hexColor: Long)
Здесь также для представления данных используется класс Rect, который представляет условный прямоугольник и принимает через конструктор высоту прямоугольника и его цвет.
При вызове метода setContent() определяется список rects из объектов Rect, и затем из них создается компонент Box, которые помещаются в FlowRow:
FlowColumn(Modifier.fillMaxSize(), maxItemsInEachColumn = 4){ rects.forEach({rect -> Box(Modifier.size(100.dp, Dp(rect.height)).padding(5.dp).background(Color(rect.hexColor))) }) }
С помощью параметра maxItemsInEachColumn = 4
указываем, что каждый столбец будет иметь не более 4 элементов:
Как и FlowRow
, компонент FlowColumn на момент написания текущей статьи находится в экспериментальном режиме, поэтому перед компонентом, который использует FlowColumn указывается аннотация
@OptIn(ExperimentalLayoutApi::class)
Возьмем чуть более сложный пример с FlowRow:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Text import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent @OptIn(ExperimentalLayoutApi::class) { 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)) FlowRow(Modifier.fillMaxSize(), maxItemsInEachRow = 3){ langs.forEach({lang -> Column(Modifier.padding(7.dp).size(115.dp, 140.dp), horizontalAlignment = Alignment.CenterHorizontally) { Box(Modifier.size(100.dp).background(Color(lang.hexColor))) Text(lang.name, fontSize = 22.sp, modifier = Modifier.padding(5.dp)) } }) } } } } data class Language(val name:String, val hexColor: Long)
Здесь данные представлены классом Language, который представляет условный язык программирования и через конструктор получает название языка и цвет. Во FlowRow задаем ограничение - не более трех элементов в 1 строке:
Аналогичный пример с FlowColumn:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowColumn import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Text import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent @OptIn(ExperimentalLayoutApi::class) { 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)) FlowColumn(Modifier.fillMaxSize(), maxItemsInEachColumn = 3){ langs.forEach({lang -> Column(Modifier.padding(7.dp).size(115.dp, 140.dp), horizontalAlignment = Alignment.CenterHorizontally) { Box(Modifier.size(100.dp).background(Color(lang.hexColor))) Text(lang.name, fontSize = 22.sp, modifier = Modifier.padding(5.dp)) } }) } } } } data class Language(val name:String, val hexColor: Long)
Здесь располагаем не более 3 элементов в одном столбце:
Стоит отметить, что если элементов много, то какая-то часть FlowRow/FlowColumn окажется вне области обзора, соответственно для просмотра невидимой части следует использовать прокрутку.
По умолчанию для FlowRow/FlowColumn прокрутка автоматически не создается. Нам самим надо определять прокрутку, например, с помощью модификатора Modifier.horizontalScroll()
(для
FlowColumn) или verticalScroll()
(для FlowRow)