- Часть 1
- Часть 2
В мае 2016 года в официальном репозитории Google на Github появился новый проект — flexbox-layout. Это менеджер макетов под Андроид, который предоставляет функциональность, схожую с CSS flexible box. В этой серии статей мы посмотрим на FlexboxLayout и попытаемся понять, как он работает, и как его лучше использовать.
Мы рассмотрим влияние XML-атрибутов на макет и поведение вложенных представлений. Чтобы было проще разбираться, я опубликовал приложение в Google Play, которое позволяет поэкспериментировать с различными вариантами. Со временем я выложу исходный код этого приложения, а пока предлагаю скачать его и поиграться с настройками.
Также хочу отметить, что в этих статьях я буду рассматривать все действия с точки зрения разработки под Андроид, т.е. буду использовать стандартные макеты Андроида и отмечать, где FlexboxLayout позволяет получить схожий результат.
Для начала добавляем зависимость в файл build.gradle:
dependencies {
compile 'com.google.android:flexbox:0.1.2'
}
И теперь можем просто использовать FlexboxLayout в XML (ну или в коде, если надо). Не буду останавливаться на этом подробнее, примеров в репозитории более чем достаточно.
В общих чертах, FlexboxLayout ближе всего к LinearLayout: дочерние элементы располагаются последовательно, один за другим. При использовании LinearLayout мы задаем ориентацию, и это подводит нас к первому атрибуту FlexboxLayout, который мы сейчас рассмотрим:
flexDirection
Этот атрибут контролирует направление расположения дочерних элементов, и, как уже говорилось, работает схоже с атрибутом orientation для LinearLayout. Значения row и column аналогичны горизонтальной и вертикальной ориентации. Однако здесь есть еще 2 возможных значения: row_reverse и column_reverse — они делают то же самое, только располагают дочерние элементы в обратном порядке.
flexDirection="row"
flexDirection="row_reverse"
Здесь нужно остановиться и ввести пару терминов: главная ось (main axis) — это направление макета, заданное в атрибуте flexDirection; и перпендикулярная к этому направлению поперечная ось (cross axis). Для row и row_reverse главной будет горизонтальная ось, а поперечной — вертикальная. Запомните эти определения, они нам еще понадобятся.
flexWrap
Первое важное различие между FlexboxLayout и LinearLayout — поведение, когда дочерние элементы достигают границы контейнера (т.е. не влезают в контейнер). В случае использования LinearLayout дочерние элементы просто обрезаются, так что при достижении границы они окажутся за пределами контейнера. Используя FlexboxLayout, мы можем контролировать это поведение с помощью атрибута flexWrap. Установив его в значение nowrap, мы заставляем все предыдущие элементы сжиматься, чтобы освободить место для нового элемента. Здесь есть возможность более тонкой настройки, мы рассмотрим это в дальнейших статьях, когда будем разбирать атрибуты дочерних элементов.
flexWrap="nowrap"
flexWrap="wrap"
flexWrap="wrap_reverse"
justifyContent
Способ позиционирования элементов вдоль главной оси контролируется атрибутом justifyContent. На первый взгляд поведение этого атрибута может показаться похожим на поведение атрибута flexDirection, однако flexDirection контролирует порядок элементов, в то время как justifyContent — относительное местоположение. Возможные значения: flex_start, flex_end, center, space_between и space_around.
justifyContent="flex_start"
justifyContent="flex_end"
justifyContent="center"
justifyContent="space_between"
justifyContent="space_around"
alignItems
Контролирует положение и размер элементов вдоль поперечной оси. Возможные значения: stretch, flex_start, flex_end, center и baseline.
alignItems="flex_start"
alignItems="flex_end"
alignItems="center"
alignItems="baseline"
alignItems="stretch"
alignContent
Вот здесь можно слегка запутаться. alignContent выглядит очень похожим на alignItems, но есть одно небольшое различие, которое, тем не менее, сильно влияет на поведение. Если alignItems контролирует, как располагаются элементы вдоль своей оси, то alignContent управляет самим размещением оси. В терминах Андроида это можно сравнить с TableRow и TableLayout: alignContent ведет себя подобно применению атрибутов к TableRow, а alignItems — это применение атрибутов к дочерним элементам — отдельным ячейкам таблицы. Возможные значения: stretch, flex_start, flex_end, center, space_between и space_around.
alignContent="flex_start"
alignContent="flex_end"
alignContent="center"
alignContent="space_between"
alignContent="space_around"
alignContent="stretch"
Лучший способ понять разницу между alignItems и alignContent — это поиграться с ними. В моем приложении установите параметры flexDirection: Row, Flex wrap: Wrap, добавьте несколько ячеек (с помощью кнопки "Add"), чтобы занять 2 ряда, установите alignContent в значение stretch, чтобы проще было оценить размеры элементов, а затем поиграйтесь значениями alignItems.
Вот такая довольно мощная и гибкая штука. Но это еще далеко не все, в следующей статье мы рассмотрим способы управления дочерними элементами по отдельности.
Приложение доступно в Google Play, исходный код будет опубликован по завершении серии статей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Комментарии (7)
almkhaj
17.05.2016 14:23Как виджет себя ведет Вы описали. Теперь хотелось бы, чтобы раскрыли следующие вопросы: в каких ситуациях лучше всего его применять, как его применение скажется на производительности приложения, в чем его предназначение.
andreich
18.05.2016 09:13Это перевод. Но надеюсь автор оригинала осветит эти моменты. Потому что производительность этой штуки действительно под вопросом.
TrueGraf
20.05.2016 16:40думаю, его предназначение в фильтрах с автозаполнением или списках вроде адресов получателей письма.
elkyzmich
Переводить новые статьи всегда нужно, но количество подобных иллюстраций было бы неплохо сократить. Хватило бы пары картинок, чтобы понять аналогию.
ookami_kb
Да, тоже сперва показалось, что количество иллюстраций избыточное. С другой стороны, если надо вернуться и быстро посмотреть конкретный случай, удобно, что не надо додумывать и тратить на это время — все под рукой.
max_ost
Размер скриншотов бы уменьшить раза в два.