Раскладка по правилам
До сих пор блоки стояли там, куда их поставили руками. Это работает, пока ничего не меняется. Но текст на кнопке переводят на другой язык, в карточку добавляют строку, из списка удаляют пункт — и всё, что расставлено руками, приходится двигать заново. Auto layout — автоматическая раскладка — решает это: фрейм сам расставляет своё содержимое по правилам.
Правил три. Направление: дети выстраиваются в ряд по горизонтали или в столбец по вертикали. Внутренние отступы: расстояние от края фрейма до содержимого — сверху, справа, снизу, слева. Промежуток: расстояние между соседними детьми. Больше ничего не нужно, чтобы собрать почти любой блок.
Вот что меняется. Кнопка «Купить» — фрейм с горизонтальной раскладкой, отступами 24 по бокам и 12 сверху-снизу, внутри текст. Напишите на ней «Добавить в корзину» — кнопка сама станет шире, отступы останутся теми же. Добавьте значок слева — он встанет перед текстом с промежутком 8, и кнопка снова подстроится.
Список — фрейм с вертикальной раскладкой и промежутком 16. Удалите третий пункт — четвёртый поднимется на его место. Добавьте новый — он встанет в конец с тем же промежутком. Двигать руками ничего не нужно.
Кто знаком с вёрсткой, узнает здесь flexbox: direction, padding, gap — те же три понятия. Это не совпадение: auto layout придуман, чтобы макет вёл себя так же, как будущая страница. Поэтому макет на auto layout переносится в код почти дословно, а макет, расставленный руками, приходится угадывать.
Hug, fill, fixed
Самое важное в auto layout — не направление и не отступы, а вопрос, который задают каждому слою внутри: каким должен быть твой размер? Ответов три.
Hug — «обнимать содержимое»: слой ровно такого размера, какого требует его содержимое. Кнопка по ширине — hug: длинный текст — широкая кнопка. Метка «Новинка» — hug. Всё, что должно подстраиваться под текст, — hug.
Fill — «заполнить»: слой занимает всё свободное место в родителе. Поле ввода в форме — fill по ширине: форма шире — поле шире. Текст описания в карточке — fill: занимает всю ширину карточки за вычетом отступов и переносится на новые строки. Если два соседа оба fill, они делят место поровну.
Fixed — фиксированный размер числом. Значок 24 на 24, аватар 40 на 40, картинка товара — ширина fill, а высота fixed 200. Fixed нужен тому, что не должно меняться ни от содержимого, ни от родителя.
Ширину и высоту задают отдельно. Кнопка: ширина hug, высота hug (или fixed 48). Строка списка: ширина fill, высота hug. Карточка в сетке: ширина fill (займёт колонки), высота hug (вырастет по содержимому). Если все слои заданы правильно, макет можно растянуть или сжать, и он поведёт себя как настоящая страница.
Типичная ошибка — оставить всё fixed, как было до auto layout. Тогда раскладка вроде бы включена, но ничего не подстраивается: длинный текст вылезает за кнопку, поле не тянется. Проверка простая: потяните край родителя и посмотрите, что происходит внутри.
Выравнивание и перенос
Когда детям в auto layout места больше, чем нужно, встаёт вопрос: где им стоять? За это отвечает выравнивание. По главному направлению — к началу, к середине или к концу. По поперечному — так же: вверху, по центру, внизу ряда.
| задача | раскладка | выравнивание |
|---|---|---|
| значок и текст в кнопке | горизонтальная | по центру по вертикали |
| шапка: логотип слева, меню справа | горизонтальная | распределить с промежутком |
| карточка: картинка, текст, кнопка | вертикальная | к началу, по левому краю |
| пустое состояние экрана | вертикальная | всё по центру |
Особый режим — распределение с промежутком (space between): первый ребёнок прижат к началу, последний — к концу, остальные — равномерно между ними. Так собирают шапку: логотип слева, корзина справа, а сколько между ними места — неважно, на любой ширине экрана они будут у краёв.
Для рядов, которые не помещаются в одну строку, есть перенос: дети, не влезшие в ширину, уходят на следующую строку. Так собирают набор меток-тегов или галерею миниатюр: на широком экране — один ряд, на узком — два-три, и макет перестраивается сам.
Иногда один слой нужно вынуть из раскладки: значок «−20 %» в углу картинки товара, крестик закрытия в углу окна. Для этого у слоя есть абсолютное положение: он остаётся внутри фрейма, но раскладка его не двигает, и он стоит там, куда его поставили. Пользуются этим редко — для наложений, а не для обычных блоков.
Выравнивание — ещё одна причина собирать блоки на auto layout. Значок и текст в кнопке, выровненные «на глаз», почти всегда стоят на пиксель мимо. Выровненные по центру правилом — стоят точно, на любом размере шрифта.
Карточка из вложенных раскладок
Настоящая сила auto layout — во вложенности. Карточка товара — это не один фрейм с раскладкой, а несколько, вложенных друг в друга, как в первом уроке.
| уровень | раскладка | размер |
|---|---|---|
| Карточка | вертикальная, отступы 16, промежуток 12 | ширина fill, высота hug |
| Картинка | — | ширина fill, высота fixed 180 |
| Блок текста | вертикальная, промежуток 4 | ширина fill, высота hug |
| Ряд цены и кнопки | горизонтальная, space between | ширина fill, высота hug |
| Кнопка | горизонтальная, отступы 16 / 8 | hug × hug |
Посмотрите, как это работает вместе. Название товара стало длинным и перенеслось на две строки — блок текста вырос, карточка вытянулась вниз, ряд с ценой сдвинулся, ничего не наехало. Карточку поставили в более широкую колонку — картинка и текст стали шире, кнопка осталась прижатой к правому краю, цена — к левому.
Промежутки внутри держат смысловые связи из второго урока: название и описание — 4 (одна мысль), текст и ряд цены — 12 (другая часть карточки), отступы карточки — 16. Все числа по шагу.
Собирают такую карточку изнутри наружу: сначала кнопка, потом ряд цены, потом блок текста, потом карточка целиком. На каждом уровне задают раскладку и режимы размеров. Сначала это кажется долгим, но собранная так карточка больше никогда не потребует ручной правки — и станет основой для компонента в седьмом уроке.
Проверка готовности — трудный тест: вставьте в название очень длинный текст, в цену — огромное число, уберите описание совсем. Хорошая карточка переживёт всё это без единого сдвига руками.