В мае 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"


flexDirection='row_reverse'
flexDirection="row_reverse"


Здесь нужно остановиться и ввести пару терминов: главная ось (main axis) — это направление макета, заданное в атрибуте flexDirection; и перпендикулярная к этому направлению поперечная ось (cross axis). Для row и row_reverse главной будет горизонтальная ось, а поперечной — вертикальная. Запомните эти определения, они нам еще понадобятся.


flexWrap


Первое важное различие между FlexboxLayout и LinearLayout — поведение, когда дочерние элементы достигают границы контейнера (т.е. не влезают в контейнер). В случае использования LinearLayout дочерние элементы просто обрезаются, так что при достижении границы они окажутся за пределами контейнера. Используя FlexboxLayout, мы можем контролировать это поведение с помощью атрибута flexWrap. Установив его в значение nowrap, мы заставляем все предыдущие элементы сжиматься, чтобы освободить место для нового элемента. Здесь есть возможность более тонкой настройки, мы рассмотрим это в дальнейших статьях, когда будем разбирать атрибуты дочерних элементов.


flexWrap='nowrap'
flexWrap="nowrap"


flexWrap='wrap'
flexWrap="wrap"


flexWrap='wrap_reverse'
flexWrap="wrap_reverse"


justifyContent


Способ позиционирования элементов вдоль главной оси контролируется атрибутом justifyContent. На первый взгляд поведение этого атрибута может показаться похожим на поведение атрибута flexDirection, однако flexDirection контролирует порядок элементов, в то время как justifyContent — относительное местоположение. Возможные значения: flex_start, flex_end, center, space_between и space_around.


justifyContent='flex_start'
justifyContent="flex_start"


justifyContent='flex_end'
justifyContent="flex_end"


justifyContent='center'
justifyContent="center"


justifyContent='space_between'
justifyContent="space_between"


justifyContent='space_around'
justifyContent="space_around"


alignItems


Контролирует положение и размер элементов вдоль поперечной оси. Возможные значения: stretch, flex_start, flex_end, center и baseline.


alignItems='flex_start'
alignItems="flex_start"


alignItems='flex_end'
alignItems="flex_end"


alignItems='center'
alignItems="center"


alignItems='baseline'
alignItems="baseline"


alignItems='stretch'
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_start"


alignContent='flex_end'
alignContent="flex_end"


alignContent='center'
alignContent="center"


alignContent='space_between'
alignContent="space_between"


alignContent='space_around'
alignContent="space_around"


alignContent='stretch'
alignContent="stretch"


Лучший способ понять разницу между alignItems и alignContent — это поиграться с ними. В моем приложении установите параметры flexDirection: Row, Flex wrap: Wrap, добавьте несколько ячеек (с помощью кнопки "Add"), чтобы занять 2 ряда, установите alignContent в значение stretch, чтобы проще было оценить размеры элементов, а затем поиграйтесь значениями alignItems.


Вот такая довольно мощная и гибкая штука. Но это еще далеко не все, в следующей статье мы рассмотрим способы управления дочерними элементами по отдельности.


Приложение доступно в Google Play, исходный код будет опубликован по завершении серии статей.

Нужно ли переводить следующие части статьи?

Проголосовал 101 человек. Воздержался 21 человек.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Поделиться с друзьями
-->

Комментарии (7)


  1. elkyzmich
    17.05.2016 01:46

    Переводить новые статьи всегда нужно, но количество подобных иллюстраций было бы неплохо сократить. Хватило бы пары картинок, чтобы понять аналогию.


    1. ookami_kb
      17.05.2016 01:48
      +2

      Да, тоже сперва показалось, что количество иллюстраций избыточное. С другой стороны, если надо вернуться и быстро посмотреть конкретный случай, удобно, что не надо додумывать и тратить на это время — все под рукой.


      1. max_ost
        17.05.2016 14:33
        +2

        Размер скриншотов бы уменьшить раза в два.


  1. almkhaj
    17.05.2016 14:23

    Как виджет себя ведет Вы описали. Теперь хотелось бы, чтобы раскрыли следующие вопросы: в каких ситуациях лучше всего его применять, как его применение скажется на производительности приложения, в чем его предназначение.


    1. andreich
      18.05.2016 09:13

      Это перевод. Но надеюсь автор оригинала осветит эти моменты. Потому что производительность этой штуки действительно под вопросом.


    1. TrueGraf
      20.05.2016 16:40

      думаю, его предназначение в фильтрах с автозаполнением или списках вроде адресов получателей письма.
      image


  1. almkhaj
    18.05.2016 09:57

    Это перевод.

    О, извините, пропустил. Спасибо за перевод.