UIStackView упрощает макет представления за счет уменьшения количества ограничений

Вступление

UIStackView - один из самых важных и мощных UIKit компонентов, представленных в iOS 9. Он настолько мощный и элегантный, что действительно ускоряет многих из нас, стремящихся отказаться от поддержки iOS 8.

Для людей, которые много работают с Auto Layout, вы знаете, что создавать NSLayoutConstraints не очень весело и легко. Поскольку каждое представление на 2D-экране имеет четыре степени свободы, это означает, что, как правило, нам нужно создать как минимум четыре ограничения для каждого представления.

Итак, вернемся к представлению стека, было ли это нововведением?

Не совсем так, поскольку эквивалент Android LinearLayout был представлен в начале вселенной (также известный как API уровня 1). Не знаю, почему Apple потребовалось восемь лет, чтобы представить этот компонент.

Но в любом случае мы все очень рады, что он наконец-то доступен.

Несмотря на то, что UIStackView значительно упростил макет представления, уменьшив количество ограничений, которые нам пришлось бы реализовать в противном случае, он все равно может стать довольно сложным и несколько запутанным.

У представления стека есть четыре основных свойства:

Первый и последний относительно просты. Мы используем axis, чтобы определить ориентацию представления стека, которая может быть vertical или horizontal. (Если стек повернут боком, он больше не должен называться стеком или должен?) Для последнего, spacing, как следует из названия, он определяет интервал между представлениями внутри представления стека. А как насчет двух оставшихся: distribution и alignment?

Хотя UIStackView стал настолько популярным и широко используется во многих приложениях, многие люди могут не понимать его полностью и использовать его неправильно.

Это то, на чем мы сосредоточимся сегодня. Мы сравним различные distribution и alignment настройки и посмотрим, чем они отличаются друг от друга.

Подготовка

Прежде чем мы начнем, нам нужно создать несколько фиктивных представлений, которые будут помещены в наше представление стека. Вот так:

let redDummy = DummyBoxView(width: 40, height: 40, color: .red)
let greenDummy = DummyBoxView(width: 30, height: 80, color: .green)
let blueDummy = DummyBoxView(width: 80, height: 30, color: .blue)

Реализация DummyBoxView очень проста. Граница пунктирная, посередине метка, указывающая относительную ширину и высоту.

Как упоминалось ранее, существует два axes (ориентации) для представления стека: horizontal или vertical. Но для простоты мы пока сосредоточимся только на горизонтальном стеке.

Для просмотра вертикального стека нам просто нужно повернуть голову на 90 градусов, верно?

Распределение

Возможные конфигурации для distribution:

  • fill
  • fillEqually
  • fillProportionally
  • equalSpacing
  • equalCentering

Давайте просто посмотрим, как они выглядят:

Два верхних графика - это equalCentering (слева) и equalSpacing (справа). Их различия не очень очевидны, особенно когда размеры подвидов аналогичны.

Для equalCentering подвиды размещаются таким образом, чтобы расстояние от центра до центра между видами было одинаковым. Для equalSpacing интервалы между видами одинаковы.

Три нижних графика: fillEqually (слева), fillProportionally (в центре), fill (справа).

Обратите внимание, что для этих трех настроек все подвиды каким-то образом изменены, чтобы заполнить представление стека. fillEqually и fillProportionally должны быть довольно четкими в соответствии с их именами. fillEqually означает, что все подвиды будут изменены так, чтобы все они имели одинаковую ширину (для просмотра горизонтального стека). fillProportionally, с другой стороны, изменит размер подвидов пропорционально их размеру.

Но что происходит с fill? Почему наша красная коробка намного шире?

С fill представление стека выберет одно подпредставление для изменения размера.

В этом случае представление стека выберет подпредставление с самым низким приоритетом объятия. Поскольку мы никогда не устанавливали его явно, все подпредставления имеют одинаковый приоритет объятия по умолчанию. Когда это произойдет, представление стека выберет тот, который будет растягиваться первым. В этом случае красный растягивается, а зеленый и синий сохраняют свой размер.

И последнее, что важно знать об этих трех fill* настройках, это то, что представление стека использует для вычислений внутренний размер содержимого подпредставления. Не размер кадра! Не размер ограничения!

Вам интересно, почему все они выровнены по нижней части представлений стека? Переходим к следующему разделу.

Выравнивание

Возможные конфигурации для alignment:

  • fill
  • top
  • firstBaseline
  • center
  • bottom
  • lastBaseline

На самом деле есть еще два, leading и trailing, которые мы пока проигнорируем, поскольку они предназначены только для просмотра вертикального стека.

Первые три довольно ясны: это bottom (вверху слева), center (вверху в середине) и top (вверху справа). Как вы можете догадаться, в предыдущем разделе все графики фактически используют выравнивание bottom.

Следующим является fill (нижний левый), где представление стека изменяет размер всех своих представлений так, чтобы они заполняли доступное пространство перпендикулярно оси представления стека.

Последние два наиболее сбивают с толку: firstBaseline (нижний средний) и lastBaseline (нижний правый). Не уверен, что мы можем многого добиться только по именам.

Давайте посмотрим на официальные определения:

  • firstBaseline: Макет, в котором представление стека выравнивает свои упорядоченные представления на основе их первой базовой линии.
  • lastBaseline: макет, в котором представление стека выравнивает свои упорядоченные представления на основе их последней базовой линии.

Это определение похоже на то, когда я спрашиваю вас, что такое «спичечный коробок», а вы говорите мне, что это «спичечный коробок». Давайте рассмотрим еще один набор примеров с большим количеством подвидов.

  • firstBaseline (слева) похож на top, где все подвиды выровнены по верхнему краю. Однако они размещаются внизу представления стека.
  • lastBaseline (справа) похож на bottom, где все подвиды выровнены по нижнему краю. Однако они размещаются в верхней части представления стека.

Мне немного сложно представить, насколько это было бы полезно. Но, видимо, есть смысл выравнивать многострочные текстовые представления. Мы не будем здесь вдаваться в подробности. Но если вам интересно, этот ответ на stackoverflow хорошо это объясняет.

Как насчет просмотра вертикального стека?

На самом деле, все осталось по-прежнему. Единственное, что нужно заменить top и bottom на leading и trailing. Под капотом это одни и те же целые числа в перечислении.

Конец

Хорошо, это все, что касается просмотра стека. Наконец, можете ли вы догадаться, какие настройки для этого представления стека?

  • Подсказка 1: это не выравнивание по низу.
  • Хайн 2: Есть один невидимый вид.

Как всегда, спасибо за чтение! Демо-код доступен на GitHub с полным набором примеров.