DGCharts饼图单指旋转时屏蔽ScrollView手势问题求助
解决DGCharts饼图单指旋转与ScrollView手势冲突问题
核心问题在于系统默认的UIRotationGestureRecognizer需要双指触发,而你使用的DGCharts饼图单指旋转逻辑要么是修改了手势的触摸参数但未显式设置,要么是通过自定义触摸事件实现的,导致之前的手势代理方法无法在单指操作时触发,进而无法阻止ScrollView的平移手势。以下是几种可行的解决方案:
方案一:修改饼图旋转手势的触摸参数
首先确认DGCharts的PieChartView是否使用了UIRotationGestureRecognizer实现单指旋转,如果是,直接修改该手势的触摸数限制,让它能被单指触发,再配合手势代理实现冲突处理:
// 初始化饼图后,找到并配置旋转手势 if let pieViewRecognizers = pieChartView.gestureRecognizers { for gestureRecognizer in pieViewRecognizers { if let rotationGesture = gestureRecognizer as? UIRotationGestureRecognizer { rotationGesture.delegate = self // 设置为单指触发 rotationGesture.minimumNumberOfTouches = 1 rotationGesture.maximumNumberOfTouches = 1 // 让ScrollView的平移手势等待旋转手势失败后再触发 scrollView.panGestureRecognizer.require(toFail: rotationGesture) } } } // 实现手势代理方法,允许旋转手势与其他手势同时识别 extension YourViewController: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return gestureRecognizer is UIRotationGestureRecognizer || otherGestureRecognizer is UIRotationGestureRecognizer } }
方案二:通过自定义手势监控饼图触摸状态
如果DGCharts的单指旋转是通过原生触摸事件(而非手势识别器)实现的,可给饼图添加一个单指平移手势,用来监控触摸状态,动态禁用/启用ScrollView的平移手势:
// 给饼图添加单指平移手势 let piePanGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePiePanGesture(_:))) piePanGesture.minimumNumberOfTouches = 1 piePanGesture.maximumNumberOfTouches = 1 piePanGesture.delegate = self pieChartView.addGestureRecognizer(piePanGesture) // 处理手势状态,动态控制ScrollView手势 @objc private func handlePiePanGesture(_ gesture: UIPanGestureRecognizer) { switch gesture.state { case .began, .changed: // 开始/持续触摸饼图时,禁用ScrollView的平移手势 scrollView.panGestureRecognizer.isEnabled = false case .ended, .cancelled, .failed: // 触摸结束/取消时,恢复ScrollView手势 scrollView.panGestureRecognizer.isEnabled = true default: break } } // 允许自定义手势与饼图自带手势同时触发 extension YourViewController: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return otherGestureRecognizer.view == pieChartView } }
方案三:通过ScrollView手势代理判断触发条件
直接给ScrollView的平移手势设置代理,在手势开始前判断触摸位置和滑动方向,决定是否允许ScrollView响应:
// 设置ScrollView平移手势的代理 scrollView.panGestureRecognizer.delegate = self extension YourViewController: UIGestureRecognizerDelegate { func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { guard let panGesture = gestureRecognizer as? UIPanGestureRecognizer else { return true } // 判断触摸点是否在饼图范围内 let touchLocation = panGesture.location(in: pieChartView) guard pieChartView.bounds.contains(touchLocation) else { // 触摸不在饼图上,允许ScrollView滑动 return true } // 判断滑动方向:如果水平滑动距离大于垂直,说明是要旋转饼图,阻止ScrollView响应 let translation = panGesture.translation(in: view) return abs(translation.y) > abs(translation.x) } }
为什么之前的方法失效?
你之前使用的shouldReceive touch方法会在触摸开始时就阻止ScrollView手势,但如果饼图的单指旋转逻辑没有触发对应的UIRotationGestureRecognizer(因为默认双指),后续的旋转操作无法被识别,导致ScrollView手势依然会干扰。而require(toFail:)也需要目标手势能被触发才能生效,默认双指的Rotation手势无法被单指触发,所以该设置无效。
内容的提问来源于stack exchange,提问作者thesuffering
相关产品推荐
相关产品推荐

