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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:23:20