简体   繁体   English

Xcode和Swift - 在UIScrollView中检测UIView的用户触摸

[英]Xcode & Swift - Detecting user touch of UIView inside of UIScrollView

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. 我通过使用UIScrollView来实现这一点,其中UIView被用作障碍物。 When the user touches a UIView, the game is over. 当用户触摸UIView时,游戏结束。

How do I detect the users touch of a UIView from within a UIScrollView? 如何在UIScrollView中检测用户对UIView的触摸? I am using Swift with Xcode Beta 4. 我正在使用Swift和Xcode Beta 4。

EDIT: 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 setting userInteractionEnabled to NO for your scroll view, the view controller will start receiving touch events since UIViewController is a subclass of UIResponder . 通过将滚动视图的userInteractionEnabled设置为NO ,视图控制器将开始接收触摸事件,因为UIViewControllerUIResponder的子类。 You can override one or more of these methods in your view controller to respond to these touches: 您可以在视图控制器中覆盖这些方法中的一个或多个以响应这些触摸:

  • touchesBegan: withEvent: touchesBegan:withEvent:
  • touchesMoved: withEvent: touchesMoved:withEvent:
  • touchesEnded: withEvent: touchesEnded:withEvent:
  • touchesCancelled: 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!")
            }
        }
    }

}

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. UITapGestureRecognizer仅返回点击,而不是点按并保持,UILongPressGestureRecognizer不提供有关位置的信息,因此您想要使用UIPanGestureRecognizer。 It continually tells you how far the touch has moved. 它会不断告诉你触摸的移动距离。

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. currentLocation是一个CGPoint,包含当前触摸的位置,无论手指滑动到何处。 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的y坐标来确定在该y处要避免的视图的x边界,并使用<或>比较器来确定如果触摸的x边界位于这些视图中的任何一个内。

Note: you have to declare location so it can be accessed in handlePan 注意:您必须声明位置,以便可以在handlePan中访问它

var location : CGPoint = CGPointZero

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM