Верстка под разные экраны: вырезы, safe area, складные и масштаб шрифта
Ты смотришь на приложение через один экран — свой. А пользователи держат тысячи разных: узкие 21:9, вырез под камеру, жесты вместо кнопок, складные, планшеты, и кто-то со шрифтом 200%, потому что иначе не видит. Верстка, которая идеальна на твоём Pixel, у них где-нибудь да поедет: кнопка «Оплатить» под панелью жестов, заголовок обрезан на середине, важный контент спрятан под «чёлкой».
Это отдельный класс багов — не логика, а геометрия. Функциональные тесты его не ловят: они кликают по элементу, даже если он наполовину за экраном. Разберём, что тут проверять.
1. Соотношения сторон
За последние годы экраны вытянулись: 16:9 ушёл, пришли 19.5:9, 20:9, 21:9. На узких экранах контент внизу уезжает, на широких — фон растягивается или появляются чёрные поля.
- Контент не обрезан и не растянут. Фоновые изображения —
cover/containосознанно, а не «как получилось». В играх — камера не режет UI по краям. - Нижняя зона. На вытянутых экранах кнопки внизу не прилипают вплотную к краю и не уходят под системные зоны.
- Крайние точки. Тестируй не «среднее» устройство, а границы: самый узкий и самый широкий из твоей матрицы, самый маленький и самый большой по физическим дюймам.
2. Вырезы и safe area
Notch, punch-hole, «остров» — вырез откусывает часть экрана сверху. Снизу — панель жестов или navigation bar. Всё важное должно жить внутри safe area.
- Ничего кликабельного и читаемого под вырезом и под панелью жестов.
- Статус-бар и его контент не перекрывают шапку.
- Полноэкранный режим (игры, видео, камера) корректно обходит вырез — контент не под ним, но и чёрных полос по бокам нет, если это не задумано.
- Правильно используются inset-API (
safeAreaInsetsна iOS,WindowInsetsна Android), а не хардкод отступов «под конкретный телефон». - Жестовая навигация vs кнопки — при жестах свайп снизу не конфликтует с твоими нижними контролами (карусели, слайдеры, «смахнуть»).
3. Складные экраны
Складные — это уже не экзотика. Главная боль: раскладывание меняет конфигурацию на лету, как поворот, только резче — меняются и размер, и соотношение.
- Фолд/анфолд не теряет состояние: введённый текст, позиция в списке, открытый экран остаются.
- Нет краша при смене конфигурации (классический Android-баг с пересозданием Activity).
- Контент адаптируется, а не просто растягивается: на развёрнутом планшетном экране — двухпанельный режим или разумные поля, а не одна колонка на всю ширину.
- Складка (hinge) не разрезает важный контент пополам.
- Continuity: свернул на внешнем экране — развернул на внутреннем, приложение продолжает с того же места.
4. Планшеты и большие экраны
Планшет — это не растянутый телефон. Одна колонка на 12 дюймов выглядит сломанной.
- Разумные поля и максимальная ширина контента, а не текст в строку на весь экран (нечитаемо).
- Где уместно — мастер-детейл (список слева, содержимое справа).
- Модалки и диалоги не занимают весь огромный экран.
- Изображения и иконки не мыльные из-за нехватки плотных ресурсов.
5. Масштаб шрифта и доступность
Пользователь может выкрутить шрифт до 200% (iOS Dynamic Type, Android Font Scale). Это одна из самых частых причин поехавшей верстки — и один из самых редко тестируемых сценариев.
- При 200% текст не обрезан и не заканчивается многоточием на важном слове.
- Кнопки и строки растут под текст, а не наезжают друг на друга.
- Текст задан в масштабируемых единицах (
spна Android, Dynamic Type /UIFontMetricsна iOS), а не вdp/фиксированных пунктах. - Двухстрочные заголовки не ломают шапку; бейджи и счётчики не вылезают за пределы.
- Проверь и обратное — минимальный масштаб — чтобы верстка не разъезжалась пустотами.
6. Клавиатура и ввод
Появление клавиатуры — это тоже изменение доступной высоты.
- Активное поле не перекрывается клавиатурой: экран поднимается/скроллится к нему (
adjustResizeна Android, keyboard avoidance на iOS). - Кнопка сабмита остаётся доступной при открытой клавиатуре или уезжает под неё предсказуемо.
- Автозаполнение не оставляет кнопку
disabled(autofill часто не триггерит валидацию — частый баг). - Правильный тип клавиатуры под поле (номер телефона — цифровая), корректные
Done/Next, переход между полями.
7. Split-screen, многооконность, PiP
Пользователь может ужать твоё приложение в половину экрана или свернуть видео в «картинку в картинке».
- В split-screen нет краша и поехавшей верстки; минимальная ширина обработана.
- Ресайз окна на лету не теряет состояние.
- Picture-in-Picture (видео) корректно сворачивается и разворачивается.
8. Ориентация
Даже если приложение «только портрет» — это надо явно зафиксировать и проверить.
- Заявленная ориентация реально заблокирована на всех экранах (включая вебвью, камеру, видео).
- Если поворот разрешён — состояние не теряется, верстка перестраивается, нет обрезки.
- Ландшафт на игре/видео обходит вырез и не прячет UI под панель жестов.
Инструменты
- Android Studio Resizable Emulator — на лету переключает phone / unfolded / tablet / desktop и меняет соотношение.
- Foldable emulator и Layout Inspector — смотреть иерархию и отступы.
- Font scale / Dynamic Type — быстро выкрутить в настройках эмулятора/симулятора.
- xcrun simctl и разные симуляторы iPhone/iPad с вырезом и без.
- Device farm (Firebase Test Lab, BrowserStack, Sauce Labs) — реальные вырезы, складные, планшеты, которых нет под рукой.
- Accessibility Inspector / Scanner — заодно ловит контраст и размеры тапов.
Чек-лист
- Самый узкий и самый широкий экран из матрицы — контент не обрезан/не растянут.
- Ничего важного под вырезом и панелью жестов (safe area).
- Отступы через inset-API, а не хардкод под конкретный телефон.
- Складной: фолд/анфолд не теряет состояние и не крашит.
- Складка не режет контент; continuity между экранами работает.
- Планшет — адаптивная верстка, а не растянутый телефон.
- Шрифт 200% — текст не обрезан, кнопки не схлопнулись.
- Текст в
sp/ Dynamic Type, не в фиксированных единицах. - Клавиатура не перекрывает активное поле, сабмит доступен.
- Split-screen и ресайз окна — без краша и потери состояния.
- Ориентация зафиксирована явно или поворот не теряет состояние.
- Проверено на device farm, а не только на своём телефоне.
Верстка — это не «мелочь дизайнеров». Кнопка под «подбородком» на 21:9 — это потерянная оплата, а обрезанный на 200% текст — это пользователь, который не может прочитать, что происходит. Геометрию надо тестировать так же системно, как и логику.