FlowRow и FlowColumn

Последнее обновление: 05.04.2024

Flow-контейнеры (FlowRow и FlowColumn) предназначены для потокового размещения содержимого, когда содержимое автоматические помещается на следующую строку или столбец, если в текущей строке/столбце место заканчилось.

FlowRow

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 в Jetpack Compose в Kotlin на Android

Стоит отметить, что FlowRow на момент написания текущей статьи находится в экспериментальном режиме, поэтому перед компонентом, который использует FlowRow указывается аннотация @OptIn(ExperimentalLayoutApi::class)

FlowColumn

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 элементов:

FlowColumn в Jetpack Compose в Kotlin на Android

Как и FlowRow, компонент FlowColumn на момент написания текущей статьи находится в экспериментальном режиме, поэтому перед компонентом, который использует FlowColumn указывается аннотация @OptIn(ExperimentalLayoutApi::class)

Применение FlowRow и FlowColumn

Возьмем чуть более сложный пример с 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 строке:

FlowRow и настройка строк в Jetpack Compose в Kotlin на Android

Аналогичный пример с 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 элементов в одном столбце:

FlowColumn и настройка столбцов в Jetpack Compose в Kotlin на Android

Стоит отметить, что если элементов много, то какая-то часть FlowRow/FlowColumn окажется вне области обзора, соответственно для просмотра невидимой части следует использовать прокрутку. По умолчанию для FlowRow/FlowColumn прокрутка автоматически не создается. Нам самим надо определять прокрутку, например, с помощью модификатора Modifier.horizontalScroll() (для FlowColumn) или verticalScroll() (для FlowRow)

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850