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

Compose自定义弹跳按钮动画点击事件失效问题求助

问题原因

你代码里同时用了clickable和pointerInput处理触摸事件,pointerInput会拦截所有触摸事件,导致clickable的onClick完全得不到触发机会,这就是点击无反应的核心原因。

解决方案

移除clickable修饰符,直接在pointerInput的触摸逻辑里处理点击回调,同时保留弹跳动画效果。另外可以优化动画逻辑,比如点击按下时缩小,抬起(或取消)时恢复,并且只有在正常抬起时才触发点击事件。

修改后的代码
fun Modifier.bounceClick(
    onClick: () -> Unit,
    animationDuration: Int = 100,
    scaleDown: Float = 0.9f
) = composed {
    val scale = remember { Animatable(1f) }
    
    this
        .scale(scale = scale.value)
        .background(
            color = Color(0xFF35898F),
            shape = RoundedCornerShape(size = 12f)
        )
        .pointerInput(Unit) {
            while (true) {
                awaitPointerEventScope {
                    // 等待按下事件
                    awaitFirstDown(requireUnconsumed = false)
                    // 按下时执行缩小动画
                    launch {
                        scale.animateTo(
                            targetValue = scaleDown,
                            animationSpec = tween(animationDuration)
                        )
                    }
                    // 等待抬起或触摸取消事件
                    val upEvent = waitForUpOrCancellation()
                    // 执行恢复原大小的动画
                    launch {
                        scale.animateTo(
                            targetValue = 1f,
                            animationSpec = tween(animationDuration)
                        )
                    }
                    // 只有用户正常抬起手指时,才触发点击回调
                    upEvent?.let { onClick() }
                }
            }
        }
}
关键改动说明
  • 移除clickable修饰符,解决触摸事件拦截冲突
  • 直接使用pointerInput内部的launch执行动画,无需额外声明rememberCoroutineScope
  • 通过waitForUpOrCancellation()的返回值判断有效点击:返回非null表示用户正常完成点击动作,此时触发onClick
  • 简化抬起阶段的动画逻辑,直接从缩小状态恢复至原大小,去掉冗余的重复设置步骤

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:25:13