ios Xcode & Swift - 在 UIScrollView 中检测用户对 UIView 的触摸

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25061732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:38:00  来源:igfitidea点击:

Xcode & Swift - Detecting user touch of UIView inside of UIScrollView

iosxcodeuiviewuiscrollviewswift

提问by user2397282

I am creating a game, similar to Flappy Bird but the user holds their finger on the screen and dodges the obstacles, rather than tapping to make the bird fly.

我正在创建一个类似于 Flappy Bird 的游戏,但用户将手指放在屏幕上并躲避障碍物,而不是敲击让鸟飞。

I am doing this by having a UIScrollView, in which UIView's are used as obstacles. When the user touches a UIView, the game is over.

我通过使用 UIScrollView 来做到这一点,其中 UIView 被用作障碍物。当用户触摸 UIView 时,游戏就结束了。

How do I detect the users touch of a UIView from within a UIScrollView? I am using Swift with Xcode Beta 4.

如何从 UIScrollView 中检测用户对 UIView 的触摸?我在 Xcode Beta 4 中使用 Swift。

EDIT: This is screenshot of the game

编辑:这是游戏的截图

This is screenshot of the game

这是游戏截图

As you can see, the user moves their finger between the grey blocks (UIViews) as they scroll up.

如您所见,用户在向上滚动时在灰色块 (UIViews) 之间移动手指。

回答by s1m0n

By setting userInteractionEnabledto NOfor your scroll view, the view controller will start receiving touch events since UIViewControlleris a subclass of UIResponder. You can override one or more of these methods in your view controller to respond to these touches:

通过设置userInteractionEnabledNO您的滚动视图,视图控制器将开始接收触摸事件,因为UIViewController是的子类UIResponder。您可以在视图控制器中覆盖这些方法中的一个或多个以响应这些触摸:

  • touchesBegan: withEvent:
  • touchesMoved: withEvent:
  • touchesEnded: withEvent:
  • touchesCancelled: withEvent:
  • touchesBegan: withEvent:
  • touchesMoved: withEvent:
  • touchesEnded: withEvent:
  • touchesCancelled: withEvent:

I created some example code to demonstrate how you could do this:

我创建了一些示例代码来演示如何执行此操作:

class ViewController: UIViewController {
    @IBOutlet weak var scrollView: UIScrollView!

    // This array keeps track of all obstacle views
    var obstacleViews : [UIView] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create an obstacle view and add it to the scroll view for testing purposes
        let obstacleView = UIView(frame: CGRectMake(100,100,100,100))
        obstacleView.backgroundColor = UIColor.redColor()
        scrollView.addSubview(obstacleView)

        // Add the obstacle view to the array
        obstacleViews += obstacleView
    }

    override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
        testTouches(touches)
    }

    override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
        testTouches(touches)
    }

    func testTouches(touches: NSSet!) {
        // Get the first touch and its location in this view controller's view coordinate system
        let touch = touches.allObjects[0] as UITouch
        let touchLocation = touch.locationInView(self.view)

        for obstacleView in obstacleViews {
            // Convert the location of the obstacle view to this view controller's view coordinate system
            let obstacleViewFrame = self.view.convertRect(obstacleView.frame, fromView: obstacleView.superview)

            // Check if the touch is inside the obstacle view
            if CGRectContainsPoint(obstacleViewFrame, touchLocation) {
                println("Game over!")
            }
        }
    }

}

回答by trumpeter201

You can programmatically add a gesture recognizer as follows

您可以按如下方式以编程方式添加手势识别器

var touch = UITapGestureRecognizer(target:self, action:"action")
scrollView.addGestureRecognizer(touch)

However, this gesture recognizer won't work for you. UITapGestureRecognizer will only return for a tap, not a tap and hold, and UILongPressGestureRecognizer doesn't give information about location, so you want to use a UIPanGestureRecognizer. It continually tells you how far the touch has moved.

但是,此手势识别器对您不起作用。UITapGestureRecognizer 只会返回点击,而不是点击并按住,并且 UILongPressGestureRecognizer 不提供有关位置的信息,因此您需要使用 UIPanGestureRecognizer。它不断告诉您触摸移动了多远。

var touch = UIPanGestureRecognizer(target:self, action:"handlePan")
scrollView.addGestureRecognizer(touch)

@IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
    let translation = recognizer.translationInView(self.view)
    recognizer.setTranslation(CGPointZero, inView: self.view)
}

You can use the constant "translation" to move your object, it represents the distance the person has slid their finger. Use that plus the location of your bird to move the bird to a new point. You have to reset the translation to zero after this function is called.

你可以使用常量“平移”来移动你的对象,它代表了人滑动手指的距离。使用它加上你的鸟的位置将鸟移动到一个新的点。调用此函数后,您必须将转换重置为零。

Edit: With the format of your game, this code should be the best method.

编辑:根据您的游戏格式,此代码应该是最好的方法。

So, all together, the code to find the location of your finger should be as follows.

因此,总而言之,查找手指位置的代码应如下所示。

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    for touch: AnyObject in touches {
        let location = touch.locationInView(yourScrollView)
    }
}


@IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
    let translation = recognizer.translationInView(self.view)
    var currentLocation : CGPoint = CGPointMake(location.x+translation.x, location.y+translation.y)
    recognizer.setTranslation(CGPointZero, inView: self.view)
}

currentLocation is a CGPoint containing the location of the current touch, wherever the finger is slid to. As I do not know how you are creating the views to be avoided, you will have to use the y coordinate of currentLocation to determine the x boundaries of the views that are to be avoided at that y, and use < or > comparators to determine if the x boundary of the touch is inside either of those views.

currentLocation 是一个包含当前触摸位置的 CGPoint,手指滑动到的任何位置。由于我不知道您如何创建要避免的视图,因此您必须使用 currentLocation 的 y 坐标来确定在该 y 处要避免的视图的 x 边界,并使用 < 或 > 比较器来确定如果触摸的 x 边界在这些视图中的任何一个内。

Note: you have to declare location so it can be accessed in handlePan

注意:你必须声明 location 以便它可以在 handlePan 中访问

var location : CGPoint = CGPointZero