Подтвердить что ты не робот

Xcode & Swift - обнаружение пользовательского касания UIView внутри UIScrollView

Я создаю игру, похожую на Flappy Bird, но пользователь держит палец на экране и уклоняется от препятствий, вместо того, чтобы нажимать, чтобы птица летала.

Я делаю это, имея UIScrollView, в котором UIView используются как препятствия. Когда пользователь касается UIView, игра заканчивается.

Как определить, как пользователи касаются UIView из UIScrollView? Я использую Swift с Xcode Beta 4.

EDIT: Это скриншот игры

This is screenshot of the game

Как вы можете видеть, пользователь перемещает палец между серыми блоками (UIViews) по мере их прокрутки вверх.

4b9b3361

Ответ 1

Установив userInteractionEnabled в NO для вашего вида прокрутки, контроллер просмотра начнет принимать события касания, так как UIViewController является подклассом UIResponder. Вы можете переопределить один или несколько из этих методов в своем контроллере просмотра, чтобы ответить на эти касания:

  • touchhesBegan: withEvent:
  • touchhesMoved: withEvent:
  • touchesEnded: withEvent:
  • touchCancelled: 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 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 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!")
            }
        }
    }

}

Ответ 2

Вы можете программно добавить распознаватель жестов следующим образом

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

Однако этот распознаватель жестов не будет работать для вас. 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)
}

Вы можете использовать постоянный "перевод" для перемещения вашего объекта, он представляет собой расстояние, на которое человек скользнул пальцем. Используйте это, а также местоположение вашей птицы, чтобы переместить птицу в новую точку. Вы должны reset преобразовать в ноль после вызова этой функции.

Изменить: в формате вашей игры этот код должен быть лучшим методом.

Итак, все вместе, код для поиска местоположения вашего пальца должен быть следующим.

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, содержащий местоположение текущего касания, куда палец скользит. Поскольку я не знаю, как вы создаете представления, которых следует избегать, вам придется использовать координату y currentLocation для определения границ x представлений, которые следует избегать при этом y, и использовать < или > компараторы, чтобы определить, находится ли граница x в любом из этих представлений.

Примечание. Вы должны объявить местоположение, чтобы его можно было получить в handlePan

var location : CGPoint = CGPointZero