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

如何将UIView的触摸事件传递给UIScrollView并实现平滑滚动?

解决方法

直接转发原生触摸事件给UIScrollView

创建自定义UIView子类,重写所有触摸相关方法,将事件直接传递给目标UIScrollView。这种方式能让UIScrollView完整处理触摸流程,包括结束时的平滑滚动:

class PassThroughView: UIView {
    // 弱引用避免循环引用
    weak var targetScrollView: UIScrollView?
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        targetScrollView?.touchesBegan(touches, with: event)
        super.touchesBegan(touches, with: event)
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        targetScrollView?.touchesMoved(touches, with: event)
        super.touchesMoved(touches, with: event)
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        targetScrollView?.touchesEnded(touches, with: event)
        super.touchesEnded(touches, with: event)
    }
    
    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        targetScrollView?.touchesCancelled(touches, with: event)
        super.touchesCancelled(touches, with: event)
    }
}

在ViewController中关联视图:

class YourViewController: UIViewController {
    @IBOutlet weak var fixedView: PassThroughView!
    @IBOutlet weak var scrollView: UIScrollView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        fixedView.targetScrollView = scrollView
    }
}

手势识别器代理转发(可选)

如果仅需处理拖拽手势,可通过手势代理同步状态给UIScrollView的内置手势,但这种方式需要手动同步更多细节,不如原生触摸转发可靠:

class YourViewController: UIViewController, UIGestureRecognizerDelegate {
    @IBOutlet weak var fixedView: UIView!
    @IBOutlet weak var scrollView: UIScrollView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
        panGesture.delegate = self
        fixedView.addGestureRecognizer(panGesture)
    }
    
    @objc func handlePan(_ gesture: UIPanGestureRecognizer) {
        guard let scrollPan = scrollView.panGestureRecognizer else { return }
        // 同步手势状态和位移
        scrollPan.state = gesture.state
        let translation = gesture.translation(in: scrollView)
        scrollPan.setTranslation(translation, in: scrollView)
        // 触发scrollView的手势处理逻辑
        scrollPan.sendActions(for: .valueChanged)
    }
    
    // 允许两个手势同时识别
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return otherGestureRecognizer == scrollView.panGestureRecognizer
    }
}

注意点

  • 确保固定位置的UIView的userInteractionEnabled属性为true,否则无法接收触摸事件。
  • 如果UIView上有需要独立响应事件的子视图,可在触摸方法中先判断触摸点是否落在子视图范围内,再决定是否转发事件给UIScrollView。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 02:54:35