在 Android 开发中,标题栏(TopBar)可以说是几乎每个页面都会用到的基础组件。尽管 Material Design3 官方提供了 TopAppBar,但往往难以满足国内复杂的 UI 视觉规范(比如严格居中、动态的右侧操作按钮、不同的背景和字体颜色等)。
在 Jetpack Compose 这个声明式 UI 框架中,基于插槽(Slot API)和高阶函数,封装一个极具扩展性且高复用的自定义标题栏变得非常简单。

1. 需求分析:一个合格的 TopBar 需要什么?
在一个标准的 App 中,标题栏通常由三部分组成:
- 左侧:返回按钮(有时不需要展示)。
- 中间:页面标题文字。
- 右侧:扩展功能区(可能是文本"提交/保存"、可能是搜索图标、也可能是分享/收藏等)。
- 样式:灵活的背景颜色和标题颜色适配深浅色模式或主题色。
基于此,可以将自定义组件的参数设计为:
Kotlin
@Composable
fun CommonTopBar(
title: String, // 必填:标题文字
onBackClick: (() -> Unit)? = null, // 选填:返回点击事件,传 null 则不显示返回键
rightContent: (@Composable () -> Unit)? = null, // 选填:右侧自定义内容(插槽)
backgroundColor: Color = Color.White, // 选填:背景色
titleColor: Color = Color.Black // 选填:文字颜色
)
2. 核心实现:声明式 UI 的魅力
看看在 Compose 中实现这样一个通用的头部组件有多简单。使用 Row 作为外层容器,并借助 Arrangement.SpaceBetween 将左中右三部分拉开。
Kotlin
@Composable
fun CommonTopBar(...) {
// 标题栏整体行布局
Row(
modifier = Modifier
.fillMaxWidth()
.height(56.dp) // 标准标题栏高度
.background(backgroundColor),
verticalAlignment = Alignment.CenterVertically, // 垂直居中
horizontalArrangement = Arrangement.SpaceBetween // 左右分散排列
) {
// 1. 左侧:返回按钮区域
Box(
modifier = Modifier.padding(horizontal = 16.dp),
contentAlignment = Alignment.Center
) {
onBackClick?.let {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "返回",
tint = titleColor,
modifier = Modifier
.clickable { onBackClick() }
.padding(8.dp) // 增加点击热区
)
}
}
// 2. 中间:标题文字
Text(
text = title,
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = titleColor,
maxLines = 1
)
// 3. 右侧:自定义扩展内容区
Box(
modifier = Modifier.padding(horizontal = 16.dp),
contentAlignment = Alignment.Center
) {
// 调用传入的 Composable 函数
rightContent?.invoke()
}
}
}
技术亮点解析:
- 灵活的显隐控制 (
onBackClick?.let) :
在 Compose 中,不再需要View.VISIBLE或View.GONE。直接利用 Kotlin 的 null 安全特性,当传入的onBackClick函数不为空时,才渲染返回按钮。 - Slot API (插槽设计) (
rightContent: @Composable () -> Unit) :
这是 Compose 组件封装的灵魂!没有把右侧的内容写死成某种类型(比如写死只能传 Icon 或 String),而是接收一个@Composable的高阶函数。这意味着使用这个组件的人,想在右边塞什么都可以:文字、图片、甚至是进度条,极大地提升了组件的复用率。 - 增大点击热区 (
padding和clickable的顺序) :
在 Modifier 中,修饰符的调用顺序非常重要。.clickable {}.padding(8.dp)意味着先绑定点击事件,再内缩 8dp。这样在视觉上图标较小,但用户点击图标周围 8dp 范围内的空白处依然能触发点击,极大地改善了用户的交互体验。
3. 实战演示:一套代码,千变万化
有了这个灵活的 CommonTopBar 组件,可以轻松应对各种业务场景的页面头部:
场景 1:最简标题栏(无返回键)

适用于 App 的主页:
Kotlin
CommonTopBar(title = "我是标题")
场景 2:普通带返回键的标题栏

只需要传入点击事件,返回按钮就会自动出现:
Kotlin
CommonTopBar(
title = "我是标题",
onBackClick = { /* 执行返回逻辑 */ }
)
场景 3:右侧带文字操作按钮

适合表单填写页面:
Kotlin
CommonTopBar(
title = "我是标题",
onBackClick = { /* 返回 */ },
rightContent = {
Text("提交", color = Color.Blue, modifier = Modifier.clickable { /* 提交 */ })
}
)
场景 4:右侧带图标(如搜索或收藏)

适合资讯详情页或列表页:
Kotlin
CommonTopBar(
title = "文章详情",
onBackClick = { /* 返回 */ },
rightContent = {
Icon(
imageVector = Icons.Default.Favorite,
contentDescription = "收藏",
tint = Color.Red
)
}
)
场景 5:完全自定义的主题颜色

某些特定页面可能需要红色沉浸式背景搭配白色字体:
Kotlin
CommonTopBar(
title = "我是标题",
onBackClick = { /* 返回 */ },
backgroundColor = Color.Red,
titleColor = Color.White
)
总结
在传统的 Android View 系统中,为了实现这么一个高度定制化的标题栏,往往需要写冗长的 XML 布局,使用各种 RelativeLayout 约束,还要在 Activity 中通过 findViewById 动态控制各种 View.GONE。
而在 Jetpack Compose 中,得益于声明式 UI 和 Kotlin 强大的 ** 高阶函数(Slot API**支持,不到 60 行代码,我们就构建出了一个极其优雅、灵活且可复用的 CommonTopBar 组件。这也是现代 Android 开发的魅力所在:让 UI 回归逻辑,让封装变得轻盈!