Взглянем на новый механизм компоновки
Если бы мне пришлось назвать аспект разработки SwiftUI, который меня сначала сбил с толку, то это были бы руководства по выравниванию. Поэтому я решил написать эту статью, чтобы попытаться немного демистифицировать их, наметить, как вы можете с ними работать, и действительно заставить их работать на вас.
Руководства по выравниванию в SwiftUI похожи на ограничения в UIKit. Нет, я беру это обратно. Они являются ограничениями в SwiftUI - только вместо того, чтобы управлять вашим экраном на микроуровне, они управляют им на макроуровне. В наши дни вам необходимо управление макросами для экранов, потому что они бывают всех форм и размеров. Однако, как и ограничения, направляющие не всегда так просты в использовании.
Первое, что вам нужно оценить, - это семантика механизма компоновки в SwiftUI. Лучшее место, чтобы узнать об этом, - Выступление Дэйва Абрахамса и Джона Харпера на WWDC 2019 по этой теме. В нем они описывают три золотых правила верстки:
- Родитель предлагает размер ребенку.
- Ребенок использует предложение, чтобы определить свой размер.
- Родитель использует размер, выбранный ребенком, для размещения указанного ребенка.
«При чем здесь направляющие для выравнивания?» вы можете спросить. Абсолютно все. Для размещения / управления пространством в SwiftUI вы используете контейнеры (ZStack, VStack и HStack). Контейнеры, которые являются родительскими в семантике выше, контейнеры, которые будут организовывать своих братьев и сестер, используя указанные правила. Вы можете повлиять на эти правила с помощью ваших руководств по выравниванию. Но подождите, есть загвоздка. Обычно семантика макета гарантирует, что направляющие макета просто не работают (по крайней мере, для фреймов). Безумно, я знаю, но именно так работает семантика по умолчанию.
Давайте рассмотрим пример. У меня есть вид, в котором я добавляю фигуру (круг). Вот код:
Он слишком большой, не правда ли? Это та семантика макета. Понимаете, вы просили круг, не указывали ему размера, а он занимал столько места, сколько мог. Нет, нам нужны некоторые правила. Добавьте ZStack и фрейм.
Лучше, но ты не хотел, чтобы он был в центре. Вы хотели, чтобы это было вверху, поэтому вы проверяете документацию, добавляете направляющую для выравнивания к фрейму и пытаетесь снова. Ничего не произошло.
Вернитесь к картинке и посмотрите на красную рамку. Точка уже находится наверху. Собственно, он тоже внизу, а также на передней и задней кромках. Конечно, вы можете придать ему большую рамку, но тогда ваш круг снова займет все это. Это уловка-22.
Что вам нужно, так это две рамки. Добавьте второй ZStack и фрейм в микс с направляющей на второй фрейм.
Это очень простой принцип, который вы можете применить, чтобы заставить работать любой макет по вашему выбору. Вам просто нужно начать думать о фреймах. Apple определила девять наиболее распространенных макетов, которые могут вам понадобиться. Измените выравнивание, которое вы использовали для переменной состояния, и посмотрите на свои варианты. Вот анимированный GIF, который поможет вам понять суть дела. Эта танцующая точка обводит все варианты выравнивания кадра, когда мы меняем размер кадра. Посмотрите внимательно, и вы увидите закономерность.
Это немного похоже на ту знаменитую игру о жизни, когда я наблюдаю, как она видоизменяется. Это только начало, но определение рамок для каждого объекта в вашем проекте и руководство по выравниванию… нет, нам нужно больше. Вот код этого танцующего бота:
Пользовательские выравнивания
Пользовательские выравнивания позволяют размещать виды относительно друг друга. Чтобы определить их, вам сначала нужно определить некоторые идентификаторы выравнивания. Это код шаблона:
Код для вертикального выравнивания выглядит следующим образом:
Эта часть, наконец, связывает два уже показанных:
extension Alignment { static let theAlignment = Alignment(horizontal: .theHorizontalAlignment, vertical: .theVerticalAlignment) }
Хорошо, теперь мы будем использовать новые идентификаторы выравнивания вместе с модификатором вида alignmentGuide
, чтобы выровнять два вида в кадре относительно друг друга. Конечный результат выглядит так - парочка танцующих ботов:
Что мы здесь смотрим? Ну, пользовательское выравнивание предусматривает, что вам нужно начать с центра, а затем добавить свои виды относительно него и друг друга. Таким образом, оба круга будут оставаться в центре, но произвольно танцевать вокруг передних / задних, верхних / нижних краев друг друга. Как и в другом примере, мы меняем размер рамки, в которой они находятся, чтобы помочь вам понять, что происходит. Обратите внимание, что идентификатор выравнивания здесь связан со стеком viewModifier
, а не с фреймом, как в первом случае.
Код, создавший это приспособление, выглядит так:
Больше настраиваемых представлений
Мы еще не закончили. Как видите, существует вторая версия модификатора представления alignmentGroup
, которая основана не на нижнем индексе, как показано выше, а на вычисленном значении:
.alignmentGuide(.myHorizontalAlignment, computeValue: {d in viewW}) .alignmentGuide(.theVerticalAlignment, computeValue: {d in viewH})
Таким образом, значение viewW
, которое вы видите в строке выше, является значением относительно ширины представления, которое он изменяет, а значение viewH
- значением относительно высоты изменяемого представления. Вот анимированный GIF, чтобы попытаться воплотить это утверждение в жизнь. В нем мы меняем выравнивание viewW
и viewH
от -64 до 96. В нашем случае значения, кратные размеру круга, равны 32.
Как видите, круги на самом деле беспорядочно - и безумно - движутся по всей площади. Здесь нет места размещения в начале, в конце, сверху или снизу. Это все координаты. Обратите внимание, что модификатор выравнивания снова находится в модификаторах стека и представления выравнивания.
На этом я подошел к концу статьи. Надеюсь, мне удалось хоть немного демистифицировать выравнивания в процессе. Продолжайте кодировать и сохраняйте спокойствие.