Как убрать прямые углы при переходе между активити
В Android прямые углы при переходе между активити возникают из clipToOutline. Используйте clipToOutline и clipChildren, чтобы обрезать контент по RoundedCorner.
Как обычно решают разработчики проблему с прямыми углами, когда переходят между активити в лаунчере? Если замедлить смену активити, можно заметить, что в месте скругления внутренние блоки, которые находятся выше угла, накладываются, и появляется прямой угол. Какие практики можно применить, чтобы это исправить? И есть ли в Android что‑то вроде CSS‑свойства overflow: hidden?
Краткий ответ
Разработчики обычно применяют clipToOutline (или clipChildren + собственный OutlineProvider) для корневой вью‑страницы, чтобы «обрезать» её по форме RoundedCorner, которую задали в windowBackground. Внутренние блоки, которые находятся над скруглением, делают фон той же формы, либо добавляют отступы, чтобы они не «выходили» за скругленный край. В качестве аналога CSS‑свойства overflow: hidden в Android служат атрибуты android:clipToOutline="true" и android:clipChildren="true".
Содержание
- Как работает автоматическое скругление в лаунчере
- Практики для корректного обрезания активити
- Аналог CSS‑свойства
overflow: hiddenв Android - Заключение
Как работает автоматическое скругление в лаунчере
Лаунчер Android использует RoundedCorner API и свойства окна (windowBackground), чтобы автоматически обрезать каждую активити под скругленные углы устройства. При переходе между активити система применяет маску, которая скрывает содержимое за скруглением. Если clipToOutline не включён, внутренние элементы могут «выходить» за пределы скругления, создавая прямой угол.
Согласно документации Android, система применяет RoundedCorner к
DecorViewокна, но только еслиclipToOutline=true. [Android Developers]
Практики для корректного обрезания активити
1. Использование clipToOutline и OutlineProvider
- В
styles.xmlзадайте для окна скругление:xml<item name="android:windowBackground">@drawable/rounded_window</item> <item name="android:clipToOutline">true</item> - В
rounded_window.xmlопределитеshapeс нужнымcornerRadius. - Для более гибкого скругления можно создать собственный
ViewOutlineProvider:Это гарантирует, что весь контент окна будет обрезан по заданной форме.kotlinclass RoundedCornerProvider(private val radius: Float) : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { outline.setRoundRect(0, 0, view.width, view.height, radius) } } // В Activity val root = findViewById<View>(android.R.id.content) root.clipToOutline = true root.outlineProvider = RoundedCornerProvider(16.dp)
Пример реализации можно увидеть в ответе на StackOverflow: ClipToOutline with cornerRadii with background [StackOverflow]
2. Применение Material Shape Appearance
Material Components позволяют задать форму окна через ShapeAppearanceOverlay.
<item name="android:background">@drawable/rounded_material</item>
<item name="android:clipToOutline">true</item>
<!-- rounded_material.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/background"/>
<corners android:radius="16dp"/>
</shape>
Если нужны разные радиусы для разных углов, используйте android:radiusX и android:radiusY для каждого угла (доступно в API 29+).
Для подробностей обратитесь к материалам от Google: Material Shape Appearance [Android Developers]
3. Работа с фоном и внутренними элементами
- Фон: Внутренние блоки, которые находятся над скруглением, делают фон той же формы, либо добавляют отступы, чтобы они не «выходили» за скругленный край.
- Отступы: Добавьте
paddingк корневой вью (например, 16dp), чтобы элементы не прилегали к скругленному углу. - Плавные границы: Если часть UI должна быть прозрачной в скругленном углу, используйте
ViewOutlineProviderсsetConvexPath, чтобы задать произвольный путь.
Как решить задачу «только верхние углы», можно посмотреть на ответ Android: how to clip only top rounded corners [StackOverflow]
4. Управление переходами между активити
- Переходы: При использовании
ActivityOptions.makeSceneTransitionAnimation()система автоматически применяет маску. Если видите прямой угол, проверьте, что в обоих активитиclipToOutline=true. - Плавность: Уменьшайте время анимации, чтобы не заметить «выход» элементов.
- Оптимизируйте: Если переходы всё равно вызывают визуальные артефакты, добавьте
android:windowDisablePreview=trueв манифесте, чтобы система не показывала превью старой активити.
Пример того, как переходы влияют на скругление, можно найти в вопросе How to add rounded corners and a mask to the interface using Transition in Compose Navigation [StackOverflow]
Аналог CSS‑свойства overflow: hidden в Android
В Android аналогом является комбинация android:clipToOutline="true" и android:clipChildren="true".
clipToOutlineобрезает содержимое вью по форме, заданнойOutlineProviderилиbackgroundсshape.clipChildrenзаставляет родительскую вью обрезать дочерние элементы, если они выходят за границы родителя.
Подробнее о работе
clipChildrenможно узнать в официальной документации Android: View#clipChildren [Android Developers]
Заключение
- Включите
clipToOutlineдля корневой вью и задайтеOutlineProviderс нужным радиусом. - Используйте Material Shape Appearance, чтобы задать форму окна и согласовать фон внутренних блоков.
- Добавляйте отступы и, при необходимости, маски для конкретных углов.
- Проверьте переходы и убедитесь, что обе активити используют одинаковую обрезку.
- Аналог
overflow: hiddenреализуется черезclipToOutlineиclipChildren.
Следуя этим практикам, вы устраните появление прямого угла при переходах между активити в лаунчере и получите плавный, эстетически корректный интерфейс.
Источники
- ClipToOutline with cornerRadii with background – StackOverflow
- ClipToOutline and CornerRadii – StackOverflow
- Android round corner layout in dialogfragment – StackOverflow
- How to make layout with rounded corners? – StackOverflow
- RoundedCorner API reference – Android Developers
- Material Shape Appearance – Android Developers
- View#clipChildren – Android Developers