Jetpack Compose 自定义标题栏终极指南:从基础到高级实战
本文将带你彻底掌握 Compose 标题栏开发,涵盖 5 种专业级实现方案 + 性能优化技巧 + 完整可运行代码。
📚 核心方案对比
方案 | 特点 | 适用场景 | 复杂度 |
---|---|---|---|
基础Row布局 | 完全自定义,灵活度高 | 简单标题栏 | ⭐ |
Material增强版 | 完美兼容MD3主题 | 标准化产品 | ⭐⭐ |
沉浸式标题 | 动态透明度/折叠效果 | 内容型APP | ⭐⭐⭐ |
多状态管理 | 集成菜单/搜索框 | 复杂交互需求 | ⭐⭐⭐⭐ |
跨平台适配 | 处理刘海屏/手势冲突 | 全屏应用 | ⭐⭐⭐⭐ |
🛠️ 5 种专业实现方案
方案1:基础标题栏(15行代码)
@Composable
fun BasicTitleBar(title: String, onBack: () -> Unit) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.padding(horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = onBack) {
Icon(Icons.Default.ArrowBack, null)
}
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.weight(1f)
)
}
}
方案2:Material3 增强版
@Composable
fun MaterialTitleBar(
title: String,
subtitle: String? = null,
actions: @Composable RowScope.() -> Unit = {}
) {
Surface(
color = MaterialTheme.colorScheme.surface,
shadowElevation = 3.dp
) {
Row(
Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(Modifier.weight(1f)) {
Text(title, style = MaterialTheme.typography.titleLarge)
subtitle?.let {
Text(it, style = MaterialTheme.typography.bodySmall)
}
}
Row(actions = actions)
}
}
}
方案3:沉浸式动态标题
@Composable
fun ImmersiveTitleBar(
scrollState: ScrollState,
title: String
) {
val alpha by remember {
derivedStateOf {
min(1f, scrollState.value / 200f)
}
}
Box(
modifier = Modifier
.fillMaxWidth()
.height(64.dp)
) {
Text(
text = title,
modifier = Modifier
.align(Alignment.BottomStart)
.padding(16.dp)
.graphicsLayer { this.alpha = alpha },
style = MaterialTheme.typography.headlineSmall
)
}
}
🚀 高级功能集成
动态菜单控制
@Composable
fun MenuTitleBar() {
var expanded by remember { mutableStateOf(false) }
Row {
// 标题...
Box {
IconButton(onClick = { expanded = true }) {
Icon(Icons.Default.MoreVert, null)
}
DropdownMenu(expanded, onDismiss = { expanded = false }) {
DropdownMenuItem(text = { Text("设置") }, onClick = {})
DropdownMenuItem(text = { Text("退出") }, onClick = {})
}
}
}
}
标题栏交互动画
val transition = updateTransition(targetState = expanded)
val elevation by transition.animateDp { if (it) 8.dp else 0.dp }
Surface(
modifier = Modifier.shadow(elevation)
) { /* ... */ }
💡 性能优化要点
-
避免重组:
@Immutable data class TitleState(val text: String, val icon: ImageVector)
-
边界条件处理:
Modifier .windowInsetsPadding(WindowInsets.systemBars) .navigationBarsPadding()
-
图片加载优化:
AsyncImage( model = "url", contentDescription = null, modifier = Modifier.size(32.dp).clip(CircleShape) )
📌 最佳实践建议:
- 简单场景直接用
Row
布局- 需要主题适配选
Material
组件- 复杂交互优先考虑状态管理架构
- 全屏应用必须处理系统手势冲突
通过本指南,你可以轻松实现从简单到企业级的标题栏需求。如果有特殊场景需求,欢迎在评论区讨论!