В Android 15 (API 35) Google продолжает продвигать иммерсивные пользовательские интерфейсы от края до края (edge-to-edge). Несмотря на то, что это улучшает дизайн современных приложений, это вносит тонкие изменения, которые могут нарушить существующие макеты — особенно если ваше приложение полагается на точную работу с системными панелями. В этой статье мы рассмотрим, как перенести приложение Jetpack Compose на API 35, и обсудим лучшие методы управления переходом к edge-to-edge UI.
Отправная точка: текущая ситуация
Рассмотрим базовую настройку Compose с белой панелью инструментов и нижней панелью навигации:
@Composable
fun MainScreen() {
Scaffold(
topBar = {
TopAppBar(
title = { Text(text = "Edge-to-Edge Example") },
actions = {
IconButton(onClick = { /* Handle settings */ }) {
Icon(Icons.Default.Settings, contentDescription = "Settings")
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.White,
titleContentColor = Color.Black
)
)
},
bottomBar = {
BottomAppBar(
containerColor = Color.White,
contentColor = Color.Black
) {
IconButton(onClick = { /* Handle home action */ }) {
Icon(Icons.Default.Home, contentDescription = "Home")
}
Spacer(modifier = Modifier.weight(1f))
IconButton(onClick = { /* Handle search action */ }) {
Icon(Icons.Default.Search, contentDescription = "Search")
}
Spacer(modifier = Modifier.weight(1f))
IconButton(onClick = { /* Handle profile action */ }) {
Icon(Icons.Default.Person, contentDescription = "Profile")
}
}
},
content = { innerPadding ->
Box(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.background(Color.Gray),
contentAlignment = Alignment.Center
) {
Text(
text = "Content goes here on API ${Build.VERSION.SDK_INT}",
fontSize = 22.sp
)
}
}
)
}
Проблема
Этот код ведет себя по-разному на API 34 и API 35 из-за изменений.
1. Строка состояния:
- API 34: Отражает серый фон содержимого благодаря своей прозрачности.
- API 35: По умолчанию белый для согласованности, но не хватает видимых значков, если они не настроены.
2. Панель навигации:
- API 34: По умолчанию черная, так как нет явной настройки.
- API 35: наследует белый цвет BottomAppBar приложения для обеспечения целостности.
Хотя эти изменения соответствуют современным стандартам дизайна, они требуют корректировки для обеспечения обратной совместимости и визуальной согласованности.
Упрощенное решение: включить Edge-to-Edge
Чтобы эффективно реализовать функциональность «от края до края», вы можете использовать WindowCompat и WindowInsetsControllerCompat для настройки:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Enable edge-to-edge mode
// This disables the default system behavior where the window content is adjusted to fit within the system bars (status and navigation bars).
// By setting this to false, your app's content is allowed to draw under the system bars, creating an immersive, edge-to-edge experience.
// You can then manage how your content interacts with these bars using insets and modifiers.
WindowCompat.setDecorFitsSystemWindows(window, false)
// Adjust status and navigation bar appearance
val insetsController = WindowInsetsControllerCompat(window, window.decorView)
insetsController.isAppearanceLightStatusBars = true
insetsController.isAppearanceLightNavigationBars = true
// Optional: Set specific colors for status and navigation bars
window.statusBarColor = android.graphics.Color.TRANSPARENT
window.navigationBarColor = android.graphics.Color.TRANSPARENT
setContent {
MainScreen()
}
}
}
Такая настройка обеспечивает edge-to-edge функциональность, а значки системной панели остаются видимыми и выровненными по теме вашего приложения.
Расширенная конфигурация: отступы окон
Для точного контроля над отступами в Jetpack Compose вы можете использовать встроенные модификаторы, такие как Modifier.windowInsetsPadding или параметр contentWindowInsets в Scaffold. Эти инструменты позволяют динамически настраивать макет приложения для размещения областей системной панели, обеспечивая отточенную работу в полноэкранном режиме.
1. Modifier.windowInsetsPadding
Этот модификатор добавляет подложку к композитным элементам на основе определенных системных вставок, таких как строки состояния, навигационные панели или системные жесты.
Box(
modifier = Modifier
.fillMaxSize()
.windowInsetsPadding(WindowInsets.systemBars)
) {
Text("Content respects system bars")
}
Значение WindowInsets.systemBars динамически регулирует отступы для строк состояния и навигации.
2. contentWindowInsets в Scaffold
Параметр contentWindowInsets гарантирует, что содержимое scaffold динамически учитывает системные элементы для правильной настройки макета.
Scaffold(
contentWindowInsets = WindowInsets.systemBars,
content = { innerPadding ->
Box(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding),
contentAlignment = Alignment.Center
) {
Text("Content adjusted for system bars")
}
}
)
3. Комбинированное использование
Для сложных макетов вы можете комбинировать Modifier.windowInsetsPadding с другими модификаторами макета, чтобы точно настроить пользовательский интерфейс вашего приложения.
Column(
modifier = Modifier
.fillMaxSize()
.windowInsetsPadding(WindowInsets.systemBars)
) {
Text("Top Content")
Spacer(modifier = Modifier.weight(1f))
Text("Bottom Content")
}
Это обеспечивает динамическое расположение контента и позволяет избежать перекрытия системных элементов.
Используя эти инструменты, вы можете создать отзывчивый и захватывающий пользовательский интерфейс, который придерживается принципов «от края до края» без ущерба для удобства использования.
Заключение
Обновление Android 15 с принципом edge-to-edge способствуют созданию более иммерсивных пользовательских интерфейсов, но требуют от разработчиков адаптации кодовой базы для поддержания совместимости и визуальной согласованности. Использование WindowCompat и WindowInsetsControllerCompat упрощает этот процесс, а расширенные конфигурации элементов обеспечивают гибкость для сложных макетов.

