FlowRow и FlowColumn – это composable-функции, похожие на Row и Column, но отличающиеся тем, что элементы переносятся на следующую строку, когда в контейнере заканчивается место. Это создаёт
несколько строк или столбцов. Количество элементов в строке также можно контролировать, задав maxItemsInEachRow или maxItemsInEachColumn. Часто для создания адаптивных макетов можно использовать FlowRow и FlowColumn – контент не будет обрезан, если элементы слишком велики для одного измерения, а использование комбинации maxItemsInEach* с Modifier.weight(weight) может помочь в создании макетов, которые при необходимости заполняют/расширяют ширину строки или столбца.
Типичный пример – чип или интерфейс фильтрации:
FlowRowОсновные функции
Чтобы использовать FlowRow или FlowColumn, создайте эти composable-функции и поместите в них элементы, которые должны следовать стандартному потоку:
@Composable private fun FlowRowSimpleUsageExample() { FlowRow(modifier = Modifier.padding(8.dp)) { ChipItem("Price: High to Low") ChipItem("Avg rating: 4+") ChipItem("Free breakfast") ChipItem("Free cancellation") ChipItem("£50 pn") } }
Этот фрагмент кода создает интерфейс, показанный выше, в котором элементы автоматически переносятся на следующую строку, когда в первой строке больше нет места.
Особенности макета с плавающим размещением
Макеты Flow имеют следующие функции и свойства, которые можно использовать для создания различных макетов в приложении.
Расположение по главной оси: горизонтальное или вертикальное.
Главная ось – это ось, на которой размещаются элементы (например, в FlowRow элементы расположены горизонтально). Параметр horizontalArrangement в FlowRow определяет, как свободное пространство распределяется между элементами.
В таблице ниже показаны примеры настройки horizontalArrangement для товаров в FlowRow.
Для горизонтального расположения установлено значение |
Результат |
|
|
|
|
|
|
|
|
|
|
|
Для FlowColumn доступны аналогичные варианты с verticalArrangement, по умолчанию – Arrangement.Top.
Расположение по поперечной оси
Поперечная ось – это ось, перпендикулярная главной. Например, на FlowRow это вертикальная ось. Чтобы изменить расположение всего содержимого контейнера по поперечной оси, используйте verticalArrangement для FlowRow и horizontalArrangement для FlowColumn.
В таблице ниже показано, как задать разные значения verticalArrangement для товаров в FlowRow.
Для вертикального выравнивания установлено значение |
Результат |
|
|
|
|
|
Для FlowColumn похожие варианты доступны в horizontalArrangement.
По умолчанию используется Arrangement.Start.
Выравнивание отдельных элементов
Возможно, вы захотите расположить отдельные элементы в строке с разным выравниванием. Это свойство отличается от verticalArrangement и horizontalArrangement тем, что выравнивает элементы внутри текущей строки. Вы можете применить это с помощью Modifier.align().
Например, если элементы в FlowRow имеют разную высоту, строка принимает высоту самого большого элемента и применяет к элементам Modifier.align(alignmentOption):
Вертикальное выравнивание установлено на |
Результат |
|
|
|
|
|
Для FlowColumn доступны похожие варианты. По умолчанию используется выравнивание Alignment.Start.
Максимальное количество элементов в строке или столбце
Параметры maxItemsInEachRow или maxItemsInEachColumn определяют максимальное количество элементов на главной оси, которое может быть в одной строке, прежде чем произойдет перенос на следующую. Значение по умолчанию – Int.MAX_INT. В этом случае в строку помещается максимально возможное количество элементов.
Например, если задать maxItemsInEachRow, в начальном макете будет только три элемента:
Максимальное значение не задано |
|
|
|
Вес товаров
Вес увеличивает элемент на основе его коэффициента и доступного пространства на строке, в которой он был размещен. Важно отметить, что FlowRow и Row по-разному используют веса для расчета ширины элемента. Для Rows вес рассчитывается на основе всех элементов в Row. При использовании FlowRow вес определяется на основе элементов в строке, в которой размещен элемент, а не всех элементов в контейнере FlowRow.
Например, если у вас есть четыре объекта, которые находятся на одной линии и имеют разные веса 1f, 2f, 1f и 3f, то общий вес будет равен 7f. Оставшееся место в строке или столбце будет разделено на 7f. Ширина каждого элемента будет рассчитываться по формуле weight * (remainingSpace / totalWeight).
Вы можете использовать сочетание Modifier.weight и максимального количества элементов с FlowRow или FlowColumn, чтобы создать макет в виде сетки. Этот подход полезен для создания адаптивных макетов, которые подстраиваются под размер вашего устройства.
Ниже приведены примеры того, как можно использовать весовые коэффициенты. Например, это может быть сетка, в которой все элементы имеют одинаковый размер, как показано ниже:
FlowRowЧтобы создать сетку с элементами одинакового размера, выполните следующие действия:
val rows = 3 val columns = 3 FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = rows ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .weight(1f) .clip(RoundedCornerShape(8.dp)) .background(MaterialColors.Blue200) repeat(rows * columns) { Spacer(modifier = itemModifier) } }
Важно: если вы добавите ещё один элемент и повторите его 10 раз вместо 9, последний элемент займет весь последний столбец, так как общий вес для всей строки равен 1f:
FlowRow для создания сетки, в которой последний элемент занимает всю ширинуВы можете комбинировать веса с другими Modifiers, например Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio) или Modifier.fillMaxWidth(fraction). Все эти модификаторы работают вместе, позволяя адаптивно изменять размер элементов в FlowRow (или FlowColumn).
Вы также можете создать чередующуюся сетку из элементов разного размера, где два элемента занимают по половине ширины, а один элемент занимает всю ширину следующего столбца:
FlowRow с чередующимися размерами строкДля этого используйте следующий код:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 2 ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .clip(RoundedCornerShape(8.dp)) .background(Color.Blue) repeat(6) { item -> // if the item is the third item, don't use weight modifier, but rather fillMaxWidth if ((item + 1) % 3 == 0) { Spacer(modifier = itemModifier.fillMaxWidth()) } else { Spacer(modifier = itemModifier.weight(0.5f)) } } }
Дробные размеры
С помощью Modifier.fillMaxWidth(fraction) можно указать размер контейнера, который должен занимать элемент. Это отличается от того, как Modifier.fillMaxWidth(fraction) работает с Row или Column, поскольку элементы Row/Column занимают процент от оставшейся ширины, а не от ширины всего контейнера.
Например, следующий код дает разные результаты при использовании FlowRow и Row:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 3 ) { val itemModifier = Modifier .clip(RoundedCornerShape(8.dp)) Box( modifier = itemModifier .height(200.dp) .width(60.dp) .background(Color.Red) ) Box( modifier = itemModifier .height(200.dp) .fillMaxWidth(0.7f) .background(Color.Blue) ) Box( modifier = itemModifier .height(200.dp) .weight(1f) .background(Color.Magenta) ) }
|
|
|
|
fillMaxColumnWidth() и fillMaxRowHeight()
Применение Modifier.fillMaxColumnWidth() или Modifier.fillMaxRowHeight() к элементу внутри FlowColumn или FlowRow гарантирует, что элементы в том же столбце или строке будут иметь ту же ширину или высоту, что и самый большой элемент в столбце/строке.
Например, в этом примере используется FlowColumn для отображения списка десертов Android. Вы можете увидеть разницу в ширине каждого элемента, когда к ним применяется Modifier.fillMaxColumnWidth(), по сравнению с тем, когда это не так и элементы переносятся.
FlowColumn( Modifier .padding(20.dp) .fillMaxHeight() .fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp), maxItemsInEachColumn = 5, ) { repeat(listDesserts.size) { Box( Modifier .fillMaxColumnWidth() .border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp)) .padding(8.dp) ) { Text( text = listDesserts[it], fontSize = 18.sp, modifier = Modifier.padding(3.dp) ) } } }
К каждому элементу применено |
|
Ширина не меняется (элементы переносятся) |
|
Рекомендуем
- Примечание. Текст ссылки показывается, когда JavaScript отключен.
- Основы макета Compose
- ConstraintLayout в Compose
- Действия в редакторе {:#editor-actions}