Ios Xcode&;Swift-在UIScrollView内部检测用户对UIView的触摸

Ios Xcode&;Swift-在UIScrollView内部检测用户对UIView的触摸,ios,xcode,uiview,uiscrollview,swift,Ios,Xcode,Uiview,Uiscrollview,Swift,我正在创建一个类似于Flappy Bird的游戏,但用户将手指放在屏幕上躲避障碍物,而不是点击使小鸟飞翔 我通过使用UIScrollView来实现这一点,其中UIView被用作障碍。当用户触摸UIView时,游戏结束 如何从UIScrollView中检测用户对UIView的触摸?我正在使用带有Xcode Beta 4的Swift 编辑:这是游戏的截图 如您所见,用户在向上滚动时在灰色块(UIView)之间移动手指。您可以通过编程方式添加手势识别器,如下所示 var touch = UITapG

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

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

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

编辑:这是游戏的截图


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

您可以通过编程方式添加手势识别器,如下所示

var touch = UITapGestureRecognizer(target:self, action:"action")
scrollView.addGestureRecognizer(touch)
但是,此手势识别器不适用于您。UIAPTgestureRecognitor将只返回点击,而不是点击并按住,并且UILongPressgestureRecognitor不提供有关位置的信息,因此您希望使用UIPangestureRecognitor。它不断地告诉你触摸移动了多远

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)
}
你可以使用恒定的“平移”来移动你的物体,它表示人滑动手指的距离。使用该值加上鸟的位置将鸟移动到新点。调用此函数后,必须将转换重置为零

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

总之,找到手指位置的代码应该如下所示

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是一个CGPoint,包含当前触摸的位置,无论手指滑向何处。由于我不知道如何创建要避免的视图,您必须使用currentLocation的y坐标来确定在该y处要避免的视图的x边界,并使用<或>比较器来确定触摸的x边界是否在这些视图中

注意:您必须声明位置,以便可以在handlePan中访问它

var location : CGPoint = CGPointZero

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

  • 触摸开始:withEvent:
  • 触摸移动:withEvent:
  • touchesEnded:withEvent:
  • 触摸已取消:withEvent:
我创建了一些示例代码来演示如何做到这一点:

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!")
            }
        }
    }

}

这看起来不错,但是当用户的手指触摸其中一个UIView时,我需要做什么才能让应用程序发送消息或其他什么?我不需要移动一只鸟或任何东西,因为只有用户的手指在互动和躲避障碍。当用户触摸多个UIView中的一个时,游戏将结束。你误解了这个问题:没有鸟:游戏是关于将手指放在屏幕上并避开障碍物。注意。你应该做的是使用touchsbegind方法来找到触摸的初始y值,然后在我给出的代码中添加常量平移的y值,然后使用一些逻辑来找出这些值是否与视图控制器的边界重叠。这是一个好方法。然而,它不是在调用touchesMoved时重新定义了touch吗?效率或许可以有所提高。CGRectContainsPoint是查找位置的方法,但是您需要在每侧的UIView上调用它两次。没错,只要用户不停地移动手指,它确实会调用TestTouchs。但是OP可能会用一些代码来代替
println(“游戏结束!”)
,这些代码会在第一次接触时将当前屏幕替换为游戏结束屏幕,所以我认为这不会是一个问题。您是对的,
CGRectContainsPoint
至少需要调用两次。但是obstacleViews数组包含所有障碍视图,包括两个“关键”视图,所以这很好。如果性能低于标准,OP始终可以优化代码,以仅检查两个“关键”视图或当前可见的视图。公平。所有的代码都在这里,也许可以创建另一个功能来检查初始触摸。你能发布一个swift 3版本吗?