Swift - How to add tap gesture to array of UIViews?

旧城冷巷雨未停 提交于 2021-01-29 01:37:41

问题


Looking to add a tap gesture to an array of UIViews - without success. Tap seems not to be recognised at this stage.

In the code (extract) below: Have a series of PlayingCardViews (each a UIView) showing on the main view. Brought together as an array: cardView. Need to be able to tap each PlayingCardView independently (and then to be able to identify which one was tapped).

@IBOutlet private var cardView: [PlayingCardView]!


override func viewDidLoad() {
    super.viewDidLoad()
    let tap = UITapGestureRecognizer(target: self, action: #selector(tapCard(sender: )))
    for index in cardView.indices {
        cardView[index].isUserInteractionEnabled = true
        cardView[index].addGestureRecognizer(tap)
        cardView[index].tag = index
    }
}

@objc func tapCard (sender: UITapGestureRecognizer) {
    if sender.state == .ended {
        let cardNumber = sender.view.tag
        print("View tapped !")
    }
}

回答1:


You need

@objc func tapCard (sender: UITapGestureRecognizer) { 
     let clickedView = cardView[sender.view!.tag] 
     print("View tapped !" , clickedView ) 
}

No need to check state here as the method with this gesture type is called only once , also every view should have a separate tap so create it inside the for - loop

for index in cardView.indices  { 
   let tap = UITapGestureRecognizer(target: self, action: #selector(tapCard(sender: )))



回答2:


let tap = UITapGestureRecognizer(target: self, action: #selector(didTapCard(sender: )))
    for (index, view) in cardView.enumerated() {
        view.isUserInteractionEnabled = true
        view.addGestureRecognizer(tap)
        view.tag = index
    }

And then in your didTapCard func you'll need to check the tag.




回答3:


You can try to pass the view controller as parameter to the views so they can call a function on parent view controller from the view. To reduce memory you can use protocols. e.x

    protocol testViewControllerDelegate: class {
        func viewTapped(view: UIView)
    }

    class testClass: testViewControllerDelegate {

    @IBOutlet private var cardView: [PlayingCardView]!


    override func viewDidLoad() {
        super.viewDidLoad()
        for cardView in self.cardView {
            cardView.fatherVC = self
        }

        }

        func viewTapped(view: UIView) {
            // the view that tapped is passed ass parameter
        }
    }




    class PlayingCardView: UIView {

        var fatherVC: testViewControllerDelegate?
        override func awakeFromNib() {
            super.awakeFromNib()
            let gr = UITapGestureRecognizer(target: self, action: #selector(self.viewDidTap))
self.addGestureRecognizer(gr)
        }

        @objc func viewDidTap() {
            fatherVC?.viewTapped(view: self)
        }
    }



回答4:


I will not recommend the selected answer. Because creating an array of tapGesture doesn't make sense to me in the loop. Better to add gesture within PlaycardView.

Instead, such layout should be designed using UICollectionView. If in case you need to custom layout and you wanted to use scrollView or even UIView, then the better approach is to create single Gesture Recognizer and add to the superview.

Using tap gesture, you can get the location of tap and then you can get the selectedView using that location.

Please refer to below example:

import UIKit

class PlayCardView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor.red
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        backgroundColor = UIColor.red
    }

}

class SingleTapGestureForMultiView: UIViewController {

    var viewArray: [UIView]!
    var scrollView: UIScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()
        scrollView = UIScrollView(frame: UIScreen.main.bounds)
        view.addSubview(scrollView)

        let tapGesture = UITapGestureRecognizer(target: self,
                                                action: #selector(tapGetsure(_:)))
        scrollView.addGestureRecognizer(tapGesture)
        addSubviews()
    }

    func addSubviews() {

        var subView: PlayCardView
        let width = UIScreen.main.bounds.width;
        let height = UIScreen.main.bounds.height;
        let spacing: CGFloat = 8.0
        let noOfViewsInARow = 3
        let viewWidth = (width - (CGFloat(noOfViewsInARow+1) * spacing))/CGFloat(noOfViewsInARow)
        let viewHeight = (height - (CGFloat(noOfViewsInARow+1) * spacing))/CGFloat(noOfViewsInARow)

        var yCordinate =  spacing
        var xCordinate =  spacing

        for index in 0..<20 {

            subView = PlayCardView(frame: CGRect(x: xCordinate, y: yCordinate, width: viewWidth, height: viewHeight))
            subView.tag = index
            xCordinate += viewWidth + spacing
            if xCordinate > width {
                xCordinate = spacing
                yCordinate += viewHeight + spacing
            }

            scrollView.addSubview(subView)
        }
        scrollView.contentSize = CGSize(width: width, height: yCordinate)
    }

    @objc
    func tapGetsure(_ gesture: UITapGestureRecognizer) {

        let location = gesture.location(in: scrollView)
        print("location = \(location)")

        var locationInView = CGPoint.zero

        let subViews = scrollView.subviews
        for subView in subViews {
            //check if it subclass of PlayCardView
            locationInView = subView.convert(location, from: scrollView)

            if subView.isKind(of: PlayCardView.self) {
                if subView.point(inside: locationInView, with: nil) {
                    // this view contains that point
                    print("Subview at \(subView.tag) tapped");
                    break;
                }
            }

        }

    }

}


来源:https://stackoverflow.com/questions/54292558/swift-how-to-add-tap-gesture-to-array-of-uiviews

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!