✏️ 在 Jetpack Compose 中,combinedClickable 让长按与普通点击优雅共存。本课详解 onLongClick 手势识别、防冲突机制及最佳实践。
| 参数 | 类型 | 说明 | 触发时机 |
|---|---|---|---|
| onClick | () -> Unit | 普通点击回调 | 手指抬起后(无长按) |
| onLongClick | () -> Unit | 长按回调 | 按住超过 ~500ms 且未移动 |
| onDoubleClick | () -> Unit | 双击回调(可选) | 两次快速点击 |
@Composable
fun LongClickExample() {
var status by remember { mutableStateOf("等待手势...") }
Box(
modifier = Modifier
.size(220.dp, 120.dp)
.background(Color(0xFFF7E8C8), shape = RoundedCornerShape(28.dp))
.combinedClickable(
onClick = { status = "👆 普通点击" },
onLongClick = { status = "⏱️ 长按触发 (500ms)" },
onDoubleClick = { status = "👆👆 双击" } // 可选
),
contentAlignment = Alignment.Center
) {
Text(
text = status,
fontSize = 18.sp,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF2D5A27)
)
}
}
✅ 共存机制:系统通过手势超时区分点击与长按。长按触发后 onClick 不会调用,避免冲突。
onClick 会被屏蔽,不会同时响应。LongPressGesture + detectTapGestures 更底层 API。onLongClick 中执行长时间操作,考虑使用协程。Modifier.pointerInput 实现更复杂的长按拖拽。@Composable
fun CustomLongClick() {
var event by remember { mutableStateOf("") }
Box(
modifier = Modifier
.size(200.dp, 100.dp)
.background(Color(0xFFF0E3C8), RoundedCornerShape(24.dp))
.pointerInput(Unit) {
detectTapGestures(
onLongPress = { offset ->
event = "长按 @ ${offset.x.toInt()}, ${offset.y.toInt()}"
},
onTap = { event = "单击" },
onDoubleTap = { event = "双击" }
)
},
contentAlignment = Alignment.Center
) {
Text(text = event, fontSize = 16.sp, color = Color(0xFF2D5A27))
}
}
💡 detectTapGestures 默认长按阈值约 500ms,可通过 longPressTimeout 参数调整。
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 列表项操作 | combinedClickable | 点击进入详情,长按弹出菜单 |
| 图片预览 | combinedClickable | 单击查看,长按保存/分享 |
| 游戏按钮 | pointerInput + detectTapGestures | 需要自定义长按时间或位置 |
| 文本选择 | combinedClickable + 拖拽 | 长按进入选择模式 |