Edge-to-edge в Android: опыт внедрения и рекомендации по тестированию |
24.06.2025 00:00 |
Всем привет! Мы – Саша Королёв и Юля Трусова, инженеры в Design System Авито. Наша команда работает над качеством интерфейсов: актуальностью, предсказуемостью, доступностью. В этой статье рассказываем про наш опыт внедрения edge-to-edge в мобильном приложении Avito для Android. Материал будет особенно вам интересен, если ваше приложение не использовало режим edge-to-edge, но ввиду последних требований от Google по переходу на target SDK 35, появилась в этом необходимость. Ведь данное обновление применяет режим по умолчанию без возможности его отключить. Из статьи вы узнаете, с какими сложностями столкнулись мы как участники большого проекта при интеграции данного режима в масштабный проект с не одной сотней экранов. Что внутри статьи:Что такое Edge-to-edge?
РазработкаПричины поддержки edge-to-edgeЖили бы и дальше себе спокойно без этого режима, но почему вдруг появилась потребность его поддержать? А все из-за перехода на target SDK 35 и идущего с ним в комплекте так называемого edge-to-edge enforcement – насильного применения режима «от края до края». Обратите внимание, что насильно данный режим применяется только для девайсов с версией Android 15+ (Android SDK 35+), то есть поддерживать edge-to-edge для предыдущих версий Android SDK (< 35) не требуется для перехода на target SDK 35. Однако сам режим edge-to-edge доступен для использования начиная с Android SDK 21+, ввиду чего при желании вы можете также распространить режим и на версии < 35. Feature-toggle для безопасного переходаКак поддержать edge-to-edge в своем приложении, можно прочитать в официальной документации, пересказывать это нет смысла, однако в этой статье мы делимся опытом Авито, как большого проекта с огромным количеством экранов, их у нас почти 1000. Напомним, что основная причина перехода на edge-to-edge – это требование Google при поднятии target SDK 35. В случае, если ваше приложение, как и приложение Авито, до поднятия target SDK не использовало режим edge-to-edge, к вопросу поднятия версии стоит отнестись с большим вниманием и трепетом. Ведь без должных обработок WindowInsets (вставок системных панелей) приложение может просто «разъехаться», а часть критичного для бизнеса функционала станет некликабельной и неюзабельной. Режим Edge-to-Edge на самом деле имеет не так много кейсов применения: в основном он используется для красивого скролла длинных списков данных. В большинстве же экранов, особенно где нет списков, как такового преимущества от использования режима «от края до края» нет. Именно поэтому для первой итерации перехода на этот режим нашей задачей как большого проекта было не сломать то, что уже работает: мы не планировали поддержать красивый edge-to-edge для всех списков на всех экранах, а хотели сделать так, чтобы UI-элементы наших экранов не съехали за системные панели, создав неприятный и дефективный внешний вид приложения. А в худшем случае они могли и вовсе отключить возможность пользователю прокликать часть критичного бизнес-функционала. Чтобы наш переход на target SDK 35 был безопасным и безболезненным, мы продумали план:
Данный подход сделал наш переход на edge-to-edge управляемым и подконтрольным с помощью remote feature-toggle. Обработка WindowInsets на экранахИсторически сложилось, что наше приложение не является single-activity, т.к. проект зародился задолго до того, как появились Fragment’ы. На данный момент у нас нет острой необходимости переводить все на single-activity, так как преимуществ от этого не видим. Именно поэтому при переходе на edge-to-edge нам было важно учесть все точки входа в UI: Activity, Fragment, Dialog, BottomSheet. Теперь опишем механизм применения edge-to-edge под feature-toggle.
Для BaseActivity в методе onCreate обрабатываем отступы для android.R.id.content. Примерно код может выглядеть так:
Для BaseFragment в методе onViewCreated обрабатываем отступы для созданной view. Примерно код может выглядеть так:
Обработка цветов системных панелейТакже стоит обратить внимание на то, что в режиме edge-to-edge теряется возможность указывать цвет для системных панелей – они становятся прозрачными (или полупрозрачными в случае с трехкнопочной панелью навигации). Чтобы сымитировать такое поведение, мы делаем force-выставление прозрачных цветов в методах применения темы Activity, так как именно в этих методах читаются такие атрибуты, как android:navigationBarColor & android:statusBarColor:
Обработка клавиатурыВ режиме edge-to-edge важно предусмотреть логику добавления отступов при появлении на экране клавиатуры. В обычном режиме регулировать поведение экранов при появлении клавиатуры можно через флаг android:windowSoftInputMode для activity в манифесте. Однако в режиме «от края до края» данный флаг не учитывается, а клавиатура является системной панелью, отступ которой важно обработать в целях поддержания корректности внешнего вида экрана. Интересный факт, что для Android SDK 30+ можно обработать анимированный показ клавиатуры, чтобы не было скачка при появлении клавиатуры, а произошло плавное поднятие UI-элементов. Данный механизм использует те же самые WindowInsets и не конфликтует с основным коллебеком setOnApplyWindowInsets. Его-то мы и используем:
OptOut-флагВместе с тем, как добавить force-применение edge-to-edge режима при переходе на target SDK 35, в новой версии Android SDK 35 также добавили и малоизвестный атрибуты темы R.attr.windowOptOutEdgeToEdgeEnforcement, позволяющий отключить насильное применение edge-to-edge при поднятии target SDK 35. Мы настоятельно не рекомендуем использовать этот флаг, так как это лишь временное решение, позволяющее отсрочить поддержание edge-to-edge-режима до следующего target SDK 36, и Google нас уже об этом предупреждает в официальной документации. С этим флагом уже не будет возможности также динамически управлять режимом edge-to-edge в рантайме, следовательно поддержать edge-to-edge лучше всего, оставаясь на target SDK 34. ТестированиеВ рамках первой итерации тестирования нам было важно:
Как выбрать девайсы?Мир Android-девайсов огромен, поэтому мы обратились за помощью к ChatGPT и вот, что он предложил: Девайсы с панелью навигации: Другие устройства для тестирования разных форм дисплея: Дальше мы уже выбирали нужные устройства из того пула, что был у нас в юните. Если у вас на руках нет нужных девайсов, можно воспользоваться альтернативными вариантами:
На что стоит обратить внимание
Кроме этого, стоит выделить время на проверки в landscape-режиме и темной теме, если вы это поддерживаете. Примеры из практикиТеория - это прекрасно, а теперь рассмотрим реальные примеры, с которыми мы столкнулись на практике. Слева - не проскроливаются списки до конца при открытой клавиатуре (в том числе и в landscape) В центре - навигационная панель не стала прозрачной/полупрозрачной Справа - экран смещен вверх - контент перекрыт выемками и прорезями для камер Клавиатура перекрывает элементы (например, боттомшит скрыт за клавиатурой).Для этого кейса визуального примера нет. Заключение Спасибо вам за уделенное статье время! Делитесь своим опытом работы с edge-to-edge в комментариях. Всем добра и меньше багов! |