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

Jetpack Compose实现Card点击、长按及保留按压动画问题求助

解决Compose Card长按事件与按压动画共存问题

要同时保留Card的按压elevation动画和添加长按事件,核心是让Card能感知到按压状态——Card的默认动画是基于内部InteractionSource触发的,用pointerInput替代自带onClick时,需要手动将按压状态同步给Card的InteractionSource,具体实现如下:

实现代码

@Composable
fun GeneralCard(
    onClick: () -> Unit,
    onLongClick: () -> Unit,
    content: @Composable () -> Unit
) {
    val interactionSource = remember { MutableInteractionSource() }
    val isPressed = remember { mutableStateOf(false) }
    // 用rememberUpdatedState避免回调变化导致pointerInput重组
    val updatedOnClick = rememberUpdatedState(onClick)
    val updatedOnLongClick = rememberUpdatedState(onLongClick)

    Card(
        elevation = CardDefaults.cardElevation(
            defaultElevation = 4.dp,
            pressedElevation = 8.dp // 保持你原来的按压层级
        ),
        interactionSource = interactionSource,
        modifier = Modifier
            .pointerInput(updatedOnClick, updatedOnLongClick) {
                detectTapGestures(
                    onPress = {
                        // 按压开始,标记状态
                        isPressed.value = true
                        // 等待按压动作结束(抬起或滑出)
                        tryAwaitRelease()
                        isPressed.value = false
                    },
                    onTap = { updatedOnClick.value() },
                    onLongPress = { updatedOnLongClick.value() }
                )
            }
    ) {
        // 将按压状态同步到Card的InteractionSource,触发动画
        LaunchedEffect(isPressed.value) {
            val pressEvent = PressInteraction.Press(PointerInputChange.Unspecified)
            if (isPressed.value) {
                interactionSource.emit(pressEvent)
            } else {
                interactionSource.emit(PressInteraction.Release(pressEvent))
            }
        }
        content()
    }
}

关键逻辑说明

  1. 状态维护:用MutableInteractionSource和isPressed变量跟踪按压状态,这是Card识别按压动作、触发elevation动画的核心。
  2. 按压同步:在detectTapGestures的onPress回调中更新按压状态,再通过LaunchedEffect将按压/释放事件发送给Card的interactionSource,让Card感知到按压动作。
  3. 性能优化:使用rememberUpdatedState包裹回调函数,避免因回调变化导致pointerInput频繁重组。

这样既实现了点击+长按的双事件逻辑,又完全保留了Card自带的按压elevation动画效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 02:00:14