You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中如何实现滚动时状态栏与顶部应用栏颜色匹配

实现滚动联动的状态栏/导航栏与应用栏颜色同步(Jetpack Compose)

核心思路

通过监听滚动组件的滚动状态,动态切换状态栏、导航栏的颜色,使其与顶部/底部应用栏的颜色保持同步,替代静态的windowInsets配置。

具体实现步骤

1. 定义滚动状态

先获取可滚动组件的ScrollState,用于监听滚动偏移:

val scrollState = rememberScrollState()

2. 动态计算颜色值

根据滚动偏移量判断是否触发颜色切换,同步应用栏与系统栏的颜色:

val isScrolled = scrollState.value > 0
// 状态栏与顶部应用栏颜色同步
val statusBarColor = if (isScrolled) {
    MaterialTheme.colorScheme.primary
} else {
    MaterialTheme.colorScheme.surface
}
// 导航栏与底部应用栏颜色同步
val navigationBarColor = if (isScrolled) {
    MaterialTheme.colorScheme.primaryContainer
} else {
    MaterialTheme.colorScheme.surface
}

3. 实时更新系统UI

使用SideEffect配合WindowCompat动态更新系统栏颜色,并处理图标对比度:

val window = LocalContext.current.findActivity()?.window
SideEffect {
    window?.let {
        // 更新状态栏颜色及图标深浅
        it.statusBarColor = statusBarColor.toArgb()
        val isStatusBarIconDark = !ColorUtils.calculateLuminance(statusBarColor) > 0.5
        WindowCompat.getInsetsController(it, it.decorView).isAppearanceLightStatusBars = isStatusBarIconDark

        // 更新导航栏颜色及图标深浅
        it.navigationBarColor = navigationBarColor.toArgb()
        val isNavigationBarIconDark = !ColorUtils.calculateLuminance(navigationBarColor) > 0.5
        WindowCompat.getInsetsController(it, it.decorView).isAppearanceLightNavigationBars = isNavigationBarIconDark
    }
}

4. 整合布局结构

将滚动状态绑定到可滚动组件,同时配置顶部/底部应用栏的动态颜色:

Scaffold(
    topBar = {
        TopAppBar(
            title = { Text("笔记详情") },
            colors = TopAppBarDefaults.topAppBarColors(
                containerColor = if (isScrolled) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface
            )
        )
    },
    bottomBar = {
        BottomAppBar(
            containerColor = if (isScrolled) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surface
        ) {
            IconButton(onClick = { /* 点击事件 */ }) {
                Icon(Icons.Filled.ArrowBack, contentDescription = "返回")
            }
        }
    }
) { paddingValues ->
    LazyColumn(
        modifier = Modifier.padding(paddingValues),
        state = scrollState
    ) {
        items(100) { index ->
            Text(
                text = "笔记内容 $index",
                modifier = Modifier.padding(16.dp),
                fontSize = 16.sp
            )
        }
    }
}

5. 辅助扩展函数

需要实现findActivity()扩展函数来获取当前Activity的Window:

fun Context.findActivity(): Activity? = when (this) {
    is Activity -> this
    is ContextWrapper -> baseContext.findActivity()
    else -> null
}

注意事项

  • 需引入androidx.core:core-ktx依赖以使用ColorUtils。
  • 深色/浅色主题下的颜色值可根据自身主题配置调整,确保对比度符合无障碍要求。

内容的提问来源于stack exchange,提问作者Ayush Singhal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:37:35