首页 > 解决方案 > 如何将触摸事件传递给另一个视图?

问题描述

我有一个带有两个 UIPickerView 子视图的 UIView,每个子视图旋转 60 度,一个顺时针方向,一个逆时针方向。我想根据用户滑动的方向分别滚动每个pickerview。由于一个在另一个之上,因此只能滚动顶部的选取器视图。因此,我希望能够在用户沿其方向滑动时滚动底部选择器视图。

截屏

我找到的最接近的答案是覆盖 hitTest,但是我无法确定滑动方向。我想我必须以某种方式使用 touchesBegan、touchesMoved 和 touchesEnded 来确定滑动的方向。

我的第一个想法是这样的,这似乎不起作用

var startPoint: CGPoint?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    startPoint = touches.first!.location(in: self)
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    guard let startPoint = startPoint else { return }

    let endPoint = touches.first!.location(in: self)

    //This condition is arbitrary
    //The actual condition will be more complex
    if startPoint.y > endPoint.y {
        pickerViewA.isUserInteractionEnabled = true
    } else {
        pickerViewB.isUserInteractionEnabled = true
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    pickerViewA.isUserInteractionEnabled = false
    pickerViewB.isUserInteractionEnabled = false
    startPoint = nil
}

标签: iosswiftiphonexcode

解决方案


此问题的可能解决方案之一是使用屏幕大小的透明视图(您的根 ViewController):

transparentView3 = MyTransparentView(frame: view.bounds)
transparentView3?.backgroundColor = UIColor.clear
view.addSubview(transparentView3!)

您可以为这个透明视图创建一个类并在那里覆盖触摸事件:

class MyTransparentView: UIView {
    
    weak var delegate: MyTransparentViewDelegate?
    var swipePoint1: CGPoint?
    var swipeTime1: Double?
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        swipePoint1 = touches.first?.location(in: self)
        swipeTime1 = event?.timestamp
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        
        if let swipePoint2 = touches.first?.location(in: self),
            let swipeTime2 = event?.timestamp,
            let swipePoint1 = swipePoint1,
            let swipeTime1 = swipeTime1 {
            
            if swipePoint1.x > swipePoint2.x && swipeTime2-swipeTime1 < 0.5  {
                delegate?.importantSwipeOccured()
            }
        }
    }
}

与使用 UIGestureRecognizers 相比,这将提供更大的灵活性。

现在,拥有两个选择器和一个透明视图的 ViewController 可以成为透明视图的委托,并将消息重定向到您的选择器:

protocol MyTransparentViewDelegate: AnyObject {
    func importantSwipeOccured()
}

func importantSwipeOccured() {
    let color2 = rotatedView2!.backgroundColor
    rotatedView2!.backgroundColor = rotatedView1!.backgroundColor
    rotatedView1!.backgroundColor = color2
}

完整的例子可以在这里找到,你可以运行项目或者只是玩代码:https ://github.com/gatamar/so61033169/blob/master/so61033169/ViewController.swift


推荐阅读