Gianfranco Gargano
Gianfranco Gargano

Reputation: 23

How recognize which UIImageview I've tapped?

I want to realize a sort of matrix editable by touch. A series of black or white cell that if tapped switch form black to withe or viceversa. For doing this i will use UIImageView arranged in stack view a Tap Gesture Recognizer. But how do I know which UIImageView was tapped? And in which way I can change the UIImage in the UIImageView?

Upvotes: 0

Views: 1024

Answers (4)

sashi_bhushan
sashi_bhushan

Reputation: 404

Assign a tag to each UIImageView and Add Tap gestures on them.

Upon tap on any view , you can get the image view tapped by :

UIImageView *imageView = gestureRecogniser.view

Upvotes: 0

Gianfranco Gargano
Gianfranco Gargano

Reputation: 23

I'solved adding a PanGestureRecognizer to the principalStackView and than i use this function with a hitTest to know which view should change color.

func pan(_ recognizer: UIPanGestureRecognizer){
    if (recognizer.state == .began ||
        recognizer.state == .changed)
    {
        let loc = recognizer.location(in: principalRowStack)
        let view = principalRowStack.hitTest(loc, with: UIEvent())
        view?.backgroundColor = .black


    }

}

Upvotes: 0

Gianfranco Gargano
Gianfranco Gargano

Reputation: 23

The code I'm using now is this, it works well. But I want to use a pan gesture (UIPanGetureRecognizer) to change colors of the UIView. How can I do?

class ViewController: UIViewController {
@IBOutlet weak var PrincipalRowStack: UIStackView!

let rowsNumber=10
let colsNumber=10

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


    super.viewDidLoad()

    var rowsStack = [UIStackView]()
    var images = [[UIView]]()
    var gestRec = [[UITapGestureRecognizer]]()
    for r in 0...rowsNumber-1 {
        rowsStack.append(UIStackView())
        rowsStack[r].axis = .horizontal
        rowsStack[r].distribution = .fillEqually
        images.append([UIView]())
        gestRec.append([UITapGestureRecognizer]())
        for c in 0...colsNumber-1{
            images[r].append(UIView())
            gestRec[r].append(UITapGestureRecognizer())
            gestRec[r][c].addTarget(self, action: #selector(ViewController.Tap(_:)))
            images[r][c].contentMode = .scaleToFill
            images[r][c].layer.borderWidth = 1
            images[r][c].layer.borderColor = UIColor(red:0.5, green:0.5, blue:0.5, alpha: 1.0).cgColor
            images[r][c].addGestureRecognizer(gestRec[r][c])
            rowsStack[r].addArrangedSubview(images[r][c])
        }
    }
    for s in rowsStack{
        PrincipalRowStack.addArrangedSubview(s)
    }

}

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



func Tap(_ recognizer: UITapGestureRecognizer) {

    if let view = recognizer.view {
        //let tag = view.tag
        //let row = tag / 10
        //let col = tag % 10
        print("Tapped!")

        if view.backgroundColor == .black {
            view.backgroundColor = .white
        } else {
            view.backgroundColor = .black
        }
    }

}
}

Upvotes: 0

vacawama
vacawama

Reputation: 154583

If they are just white and black, it would be much simpler to use a UIView and set its backgroundColor to .white or .black. You can use the tag property of the UIViews to identify them.

In your gestureRecognizer handler, the recognizer.view tells you the view that triggered the gesture.

You can assign the tags in Interface Builder. For example, if you have an 8x8 array of squares, you could use a 2-digit number where the first digit is the row and the second digit is the column. Thus, your tags would be 11, 12, ..., 87, 88.

func squareTapped(recognizer: UIGestureRecognizer) {
    if let view = recognizer.view {
        let tag = view.tag
        let row = tag / 10
        let col = tag % 10
        print("The view at row \(row), column \(col) was tapped")

        if view.backgroundColor == .black {
            view.backgroundColor = .white
        } else {
            view.backgroundColor = .black
        }
    }
}

If you do want to use images, then load the images as properties of your viewController and assign them based upon the row and column of your image. Here I have used an Outlet Collection to hold all of the UIImageViews. In Interface Builder, you'd connect each of your cells to the squares property.

class BoardViewController: UIViewController {
    let blackImage = UIImage(named: "blackImage")!
    let whiteImage = UIImage(named: "whiteImage")!
    @IBOutlet var squares: [UIImageView]!
    var recognizersAdded = false

    func setUpBoard() {
        for imageview in squares {
            if !recognizersAdded {
                let recognizer = UITapGestureRecognizer(target: self, action: #selector(squareTapped))
                imageview.addGestureRecognizer(recognizer)
                imageview.isUserInteractionEnabled = true
            }

            let tag = view.tag
            let row = tag / 10
            let col = tag % 10

            // Just for demo purposes, set up a checkerboard pattern
            if (row + col) % 2 == 0 {
                imageview.image = blackImage
            } else {
                imageview.image = whiteImage
            }
        }
        recognizersAdded = true
    }

    func squareTapped(recognizer: UIGestureRecognizer) {
        if let view = recognizer.view as? UIImageView {
            let tag = view.tag
            let row = tag / 10
            let col = tag % 10
            print("The view at row \(row), column \(col) was tapped")

            if view.image == blackImage {
                view.image = whiteImage
            } else {
                view.image = blackImage
            } 
        }
    }
}

Upvotes: 2

Related Questions