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

Flutter中实现多手势识别:类WhatsApp录音按钮开发问题

实现类似WhatsApp的录音按钮滑动手势检测

核心逻辑很清晰:长按触发录音后,持续监听触摸点的坐标变化,通过计算当前坐标与初始长按坐标的偏移量,判断滑动方向(上滑/左滑),达到设定阈值后触发对应操作。

Android 实现(Kotlin)

通过OnLongClickListener启动录音,同时配合OnTouchListener监听后续触摸移动事件:

private var isLongPressActive = false
private var initialTouchX = 0f
private var initialTouchY = 0f
// 滑动阈值(dp转px,适配不同分辨率)
private val swipeThreshold = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20f, resources.displayMetrics).toInt()

recordButton.setOnLongClickListener {
    // 启动录音
    startRecording()
    isLongPressActive = true
    true
}

recordButton.setOnTouchListener { _, event ->
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            // 记录初始触摸坐标
            initialTouchX = event.x
            initialTouchY = event.y
            false
        }
        MotionEvent.ACTION_MOVE -> {
            if (isLongPressActive) {
                val deltaX = event.x - initialTouchX
                val deltaY = event.y - initialTouchY

                // 判断左滑:X轴负向偏移,且绝对值超过阈值,优先判断单一方向
                if (deltaX < -swipeThreshold && Math.abs(deltaX) > Math.abs(deltaY)) {
                    // 执行左滑操作(比如取消录音)
                    onSwipeLeft()
                    isLongPressActive = false
                }
                // 判断上滑:Y轴负向偏移,且绝对值超过阈值
                else if (deltaY < -swipeThreshold && Math.abs(deltaY) > Math.abs(deltaX)) {
                    // 执行上滑操作(比如锁定录音)
                    onSwipeUp()
                }
            }
            true
        }
        MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
            if (isLongPressActive) {
                // 结束录音
                stopRecording()
                isLongPressActive = false
            }
            true
        }
        else -> false
    }
}

关键注意点:

  • 用isLongPressActive标记长按状态,过滤非长按的误触移动事件
  • 比较X/Y偏移的绝对值,确保是单一方向滑动,避免斜滑误判
  • 左滑后可直接终止长按状态,上滑通常需保持录音(如WhatsApp的锁定录音逻辑)

iOS 实现(Swift)

基于UILongPressGestureRecognizer处理长按及后续滑动逻辑:

var isLongPressActive = false
var initialTouchPoint: CGPoint = .zero
let swipeThreshold: CGFloat = 20 // 滑动阈值(可转dp适配多分辨率)

let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
recordButton.addGestureRecognizer(longPressGesture)

@objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
    switch gesture.state {
    case .began:
        // 启动录音
        startRecording()
        isLongPressActive = true
        initialTouchPoint = gesture.location(in: recordButton)
    case .changed:
        guard isLongPressActive else { return }
        let currentPoint = gesture.location(in: recordButton)
        let deltaX = currentPoint.x - initialTouchPoint.x
        let deltaY = currentPoint.y - initialTouchPoint.y
        
        // 判断左滑
        if deltaX < -swipeThreshold && abs(deltaX) > abs(deltaY) {
            onSwipeLeft()
            isLongPressActive = false
            gesture.state = .ended
        }
        // 判断上滑
        else if deltaY < -swipeThreshold && abs(deltaY) > abs(deltaX) {
            onSwipeUp()
        }
    case .ended, .cancelled, .failed:
        if isLongPressActive {
            stopRecording()
            isLongPressActive = false
        }
    default:
        break
    }
}

关键注意点:

  • 在changed状态实时计算坐标偏移,判断滑动方向
  • 左滑后手动将手势状态设为.ended,避免后续事件干扰
  • 可根据需求添加滑动过程中的UI反馈(如按钮跟随滑动位移)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:07:18