4. 基础按钮与点击事件
Button 的最小可用结构
Compose 的 Button 是一个封装好的可点击容器:它内部组合了 Surface、Row 和 Text,并自动处理水波纹、最小触摸尺寸与无障碍语义。使用时只需要提供两个核心参数:onClick 回调与按钮内容。
@Composable
fun CounterButton() {
var count by remember { mutableStateOf(0) }
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(text = "点击次数:$count", fontSize = 20.sp)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { count++ }) {
Text(text = "点我 +1")
}
}
}
关键点在于 count 使用 remember { mutableStateOf(0) } 保存。当 onClick 中执行 count++ 时,Compose 会读取到状态变化并重组 Text,界面上的数字随之刷新。若把 count 写成普通局部变量,点击后数值虽然改变,但不会触发重组,界面不会更新。
状态更新与重组链路
下面这张图展示了从手指按下到界面反馈的完整信号链:点击事件进入 onClick,修改 MutableState,Compose 侦测到读取该状态的可组合项并触发重组,最终 Text 用新值重新绘制。
点击反馈的三种常见形态
“显示反馈”不一定只是数字变化。根据任务需要,可以在 onClick 中更新不同类型的状态,让界面给出不同层次的反馈:
- 计数反馈:用
Int状态记录点击次数,适合点赞、加购等场景。 - 开关反馈:用
Boolean状态切换文案或颜色,例如“已关注 / 关注”。 - 瞬时反馈:点击后把状态置为
true,配合LaunchedEffect延时复位,实现“已复制”提示。
@Composable
fun ToggleFollowButton() {
var followed by remember { mutableStateOf(false) }
Button(onClick = { followed = !followed }) {
Text(text = if (followed) "已关注" else "关注")
}
}
这里 followed 同时决定按钮文案,点击后状态取反,按钮文字立即切换。注意状态必须定义在 Button 外部,否则每次重组都会重新初始化为 false,点击将看不到任何变化。
如果点击后界面没有更新,优先检查三件事:状态是否用
remember 保存、状态是否定义在会重组的可组合项作用域内、onClick 中是否真的修改了该状态。可复用的点击反馈检查清单
| 检查项 | 正确做法 | 常见错误 |
|---|---|---|
| 状态声明 | var count by remember { mutableStateOf(0) } | 使用普通 var count = 0 |
| 状态位置 | 放在 Button 外层的可组合项中 | 写在 Button 的 lambda 内部 |
| 事件绑定 | Button(onClick = { count++ }) | 忘记传 onClick 或写成空 lambda |
| 反馈呈现 | Text 读取状态并显示 | 只改状态但界面没有读取它 |