如何将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
相关产品推荐
相关产品推荐

