Material3 NavigationBar如何同步设置系统导航栏colorElevation为1.dp?
解决方案
要同步Compose NavigationBar与Android系统导航栏的elevation,需要分别处理Compose组件层面和系统Window层面的设置,同时兼顾页面复用后的状态恢复。以下是最优实现方案:
核心思路
NavigationBar的tonalElevation是Compose组件自身的阴影效果,而系统导航栏的elevation是Android Window层面的属性,两者独立。需要通过DisposableEffect绑定当前页面的生命周期,设置系统导航栏的elevation并在页面销毁时恢复原有状态,避免影响其他页面。
完整代码实现
@Composable fun MainScreen(navigationTabs: List<NavigationTab>) { val view = LocalView.current val window = remember { (view.context as Activity).window } val targetElevation = 1.dp // 与NavigationBar的tonalElevation保持一致 // 绑定生命周期:设置系统导航栏elevation,页面销毁时恢复原有状态 DisposableEffect(targetElevation) { val originalElevation = window.navigationBarElevation val originalColor = window.navigationBarColor var originalAppearance = 0 // 应用新的系统导航栏设置 window.navigationBarElevation = targetElevation.toPx() window.navigationBarColor = Color.Transparent.toArgb() // 适配透明导航栏 // 兼容Android 11(API 30)及以上版本的阴影控制 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val insetsController = window.insetsController originalAppearance = insetsController?.systemBarsAppearance ?: 0 // 确保显示系统导航栏阴影 insetsController?.setSystemBarsAppearance( originalAppearance or WindowInsetsController.APPEARANCE_SHOW_NAVIGATION_BAR_SHADOW, WindowInsetsController.APPEARANCE_SHOW_NAVIGATION_BAR_SHADOW ) } else { // 低版本开启系统栏背景绘制权限,确保阴影显示 window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) } // 页面销毁时恢复系统导航栏原有配置 onDispose { window.navigationBarElevation = originalElevation window.navigationBarColor = originalColor if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.insetsController?.setSystemBarsAppearance( originalAppearance, WindowInsetsController.APPEARANCE_SHOW_NAVIGATION_BAR_SHADOW ) } } } Scaffold( content = { padding -> Box(modifier = Modifier.padding(bottom = padding.calculateBottomPadding())) { CurrentTab() } }, bottomBar = { NavigationBar( containerColor = MaterialTheme.colorScheme.surface, contentColor = MaterialTheme.colorScheme.secondaryContainer, tonalElevation = targetElevation, ) { navigationTabs.forEach { TabNavigationItem(it) } } }, ) }
关键细节说明
- 生命周期绑定:使用
DisposableEffect确保只有当前页面显示时才修改系统导航栏配置,页面销毁后自动恢复,不会影响其他复用该系统导航栏的页面。 - elevation同步:将系统导航栏的
navigationBarElevation设置为与NavigationBar的tonalElevation相同的像素值(通过dp.toPx()转换)。 - 透明导航栏适配:设置
window.navigationBarColor = Color.Transparent.toArgb()确保系统导航栏保持透明,同时开启阴影显示权限。 - 版本兼容:针对Android 11及以上版本使用
WindowInsetsController控制阴影,低版本通过Window flags开启背景绘制权限。
内容的提问来源于stack exchange,提问作者mitua1221
相关产品推荐
相关产品推荐

