mobile-qachecklistsaccessibility

Верстка под разные экраны: вырезы, 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 — заодно ловит контраст и размеры тапов.

Чек-лист

  1. Самый узкий и самый широкий экран из матрицы — контент не обрезан/не растянут.
  2. Ничего важного под вырезом и панелью жестов (safe area).
  3. Отступы через inset-API, а не хардкод под конкретный телефон.
  4. Складной: фолд/анфолд не теряет состояние и не крашит.
  5. Складка не режет контент; continuity между экранами работает.
  6. Планшет — адаптивная верстка, а не растянутый телефон.
  7. Шрифт 200% — текст не обрезан, кнопки не схлопнулись.
  8. Текст в sp / Dynamic Type, не в фиксированных единицах.
  9. Клавиатура не перекрывает активное поле, сабмит доступен.
  10. Split-screen и ресайз окна — без краша и потери состояния.
  11. Ориентация зафиксирована явно или поворот не теряет состояние.
  12. Проверено на device farm, а не только на своём телефоне.

Верстка — это не «мелочь дизайнеров». Кнопка под «подбородком» на 21:9 — это потерянная оплата, а обрезанный на 200% текст — это пользователь, который не может прочитать, что происходит. Геометрию надо тестировать так же системно, как и логику.