是否可以从touchesBegan或touchesMoved中取消触摸?

时间:2016-11-18 21:41:13

标签: ios iphone swift uigesturerecognizer uitouch

在UIViewController的主视图中,我有一个mapView和另一个视图(让我们说视图A),它位于mapView之上。它们都具有等于self.view.bounds的帧。视图A是一个可调整大小的矩形,类似于用于裁剪图像的矩形。我的目标是让用户在地图上指定一个区域。因此,我希望用户能够放大地图以及更改矩形宽度和高度比例,因为只让视图A成为不可实现的方块会限制它太多。

我从GitHub https://github.com/justwudi/WDImagePicker获得了这个项目,我正在使用可调整大小的矩形功能。在Github链接的第二张图片中,有一个8点的矩形和外面的阴影区域。如果用户触摸阴影区域,我希望能够让触摸传递到视图A后面的地图。只有当用户点击点内或点上的区域(以便他想调整矩形的大小)时,我才希望视图A能够识别触摸。所以,我在视图A上修改了触摸代码,并且具有:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {

        if cropBorderView.frame.contains(touch.location(in: self)){
            print("touch contains  - touchesbegan")
            //self.isUserInteractionEnabled = true
        }
        else{
            print("Touch does not contain - touchesbegan")
            self.touchesCancelled(touches, with: event)
            //return
        }
        let touchPoint = touch.location(in: cropBorderView)

        anchor = self.calculateAnchorBorder(touchPoint)
        fillMultiplyer()
        resizingEnabled = true
        startPoint = touch.location(in: self.superview)
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("inside touches moved")
    if let touch = touches.first {
        if cropBorderView.frame.contains(touch.location(in: self)){
            print("touch contains - touchesmoved")
            //self.isUserInteractionEnabled = true
        }
        else{
            print("Touch does not contain - touchesmoved ")
            self.touchesCancelled(touches, with: event)
            //return
        }

        if resizingEnabled! {
            self.resizeWithTouchPoint(touch.location(in: self.superview))
        }
    }
}

当我按照我想要的内外点击时确实识别出触摸,但是当我点击外面时它并没有停止触摸。这意味着调用self.touchesCancelled(touches, with: event)无效。调用return会导致崩溃并且不起作用。有没有解决这个问题的方法?

感谢您的时间和考虑。

1 个答案:

答案 0 :(得分:0)

touchesCancelled(_:with:)只是UITouch的通知,它不会以这种方式工作。 据我了解,您在叠加层UIView中实施了触摸处理程序,如果是这样,您可以尝试将self.touchesCancelled(touches, with: event)的调用替换为cancelTracking(with:)UIControl函数{3}}:

else {
    print("Touch does not contain - touchesmoved ")
    self.cancelTracking(with event)
}
  

根据hitTest:

更新解决方案

我已检查过可能的解决方案,您似乎可以使用hitTest:来避免不必要的触摸识别。以下示例是Swift Playground,您可以点击并拖动触摸,看看控制台中发生了什么:

import UIKit
import PlaygroundSupport

class JSGView : UIView {

    var centerView = UIView()

    override func didMoveToSuperview() {
        frame = CGRect(x: 0, y: 0, width: 320, height: 480)
        backgroundColor = UIColor.clear

        centerView.frame = CGRect(x: 110, y: 190, width: 100, height: 100)
        centerView.backgroundColor = UIColor.blue
        addSubview(centerView)
    }

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

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            if (hitTest(touch.location(in: self), with: event) != nil) {
                print("Touch passed hit test and seems valid")
                super.touchesCancelled(touches, with: event)
                return
            }
        }

        print("Touch isn't passed hit test and will be ignored")
        super.touchesMoved(touches, with: event)
    }

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if centerView.bounds.contains(centerView.convert(point, from: self)) {
            return centerView
        }
        return nil
    }
}

class JSGViewController : UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
        let customView = JSGView()
        view.addSubview(customView)
    }
}

let controller = JSGViewController()
PlaygroundPage.current.liveView = controller.view