Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if tap happened in a specific place

I am trying to check if a tap is happening in a specific region on the screen. I've set up a TapGestureRecognizer this is the code I have right now:

func handleTap(tap: UITapGestureRecognizer) {
    var point = tap.locationInView(self.view)
    println("tapped")

    if (tap.state == UIGestureRecognizerState.Ended)
    {
        if (CGRectContainsPoint(self.Region.frame, point)) {
            println("touch")
            var y = kbHeight - textYoutube.center.y
            youTextConst.constant += y
        }
    }
}

The app recognized the tap but not the tap in the specific region, What's wrong with the code?

UPDATE

I don't know if it matters but the Region is a TextView

like image 796
Omer Avatar asked Mar 06 '15 16:03

Omer


2 Answers

(NOTE: I am assuming that self.Region is a UIView. You do not explain what it is in your question, so I have to guess what it might be. By the way, please do not use a capital letter for the name of a property. I am doing this only to give you an easy match to your own code.)

Think about coordinate systems. You are saying

var point = tap.locationInView(self.view)

That means that point is in self.view's coordinate system. But that's the wrong coordinate system if you're going to call CGRectContainsPoint. Before you can work out the relationship between point and self.Region, you need to get point into the same coordinate system as self.Region:

point = self.Region.convertPoint(point, fromView:self.view)

Now you can use self.Region.bounds, which is in the same coordinate system as the new value of point:

if CGRectContainsPoint(self.Region.bounds, point)
like image 147
matt Avatar answered Oct 18 '22 17:10

matt


My first answer, even with the sketch, was messy. I've deleted it.

So here are multiple ways to achieve what you're looking for. We'll assume that your region is an UIView.

Solution 1

You are retrieving the point from the main view, so you need to check if the frame of your regionView contains your point.

import UIKit

class ViewController: UIViewController {

    @IBOutlet var regionView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let tap = UITapGestureRecognizer()
        tap.addTarget(self, action: "handleTap:")

        self.view.addGestureRecognizer(tap)
    }

    func handleTap(tap: UITapGestureRecognizer) {
        if (tap.state == UIGestureRecognizerState.Ended) {
            println("[handleTap] Tap ended")

            var point = tap.locationInView(self.view)

            println("[handleTap] Tap point : x\(point.x) ; y\(point.y) (in self.view)")

            if (CGRectContainsPoint(self.regionView.frame, point)) {
                println("[handleTap] Tap is inside regionView")
            }

            println()
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

Solution 2

You are retrieving the point and convert it to the inside regionView coordinates system. So you need to check if the point is within bounds of your regionView.

import UIKit

class ViewController: UIViewController {

    @IBOutlet var regionView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let tap = UITapGestureRecognizer()
        tap.addTarget(self, action: "handleTap:")

        self.view.addGestureRecognizer(tap)
    }

    func handleTap(tap: UITapGestureRecognizer) {
        if (tap.state == UIGestureRecognizerState.Ended) {
            println("[handleTap] Tap ended")

            var point = tap.locationInView(self.view)

            println("[handleTap] Tap point : x\(point.x) ; y\(point.y) (in self.view)")

            point = self.regionView.convertPoint(point, fromView: self.view)

            println("[handleTap] Tap point converted : x\(point.x) ; y\(point.y) (in self.regionView)")

            if (CGRectContainsPoint(self.regionView.bounds, point)) {
                println("[handleTap] Tap is inside regionView")
            }

            println()
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

Solution 3

You get the point from your regionView directly. So you don't need to convert it, however you still need to check if it's within its bounds like solution 2.

import UIKit

class ViewController: UIViewController {

    @IBOutlet var regionView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let tap = UITapGestureRecognizer()
        tap.addTarget(self, action: "handleTap:")

        self.view.addGestureRecognizer(tap)
    }

    func handleTap(tap: UITapGestureRecognizer) {
        if (tap.state == UIGestureRecognizerState.Ended) {
            println("[handleTap] Tap ended")

            var point = tap.locationInView(self.regionView)

            println("[handleTap] Tap point : x\(point.x) ; y\(point.y) (in self.view)")

            if (CGRectContainsPoint(self.regionView.bounds, point)) {
                println("[handleTap] Tap is inside regionView")
            }

            println()
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

Alternatively, you can only set your gesture recognizer on the regionView : self.regionView.addGestureRecognizer(tap).

Let me know if it helped !

like image 21
lchamp Avatar answered Oct 18 '22 17:10

lchamp