简体   繁体   English

Swift - 如何将点击手势添加到 UIViews 数组?

[英]Swift - How to add tap gesture to array of UIViews?

Looking to add a tap gesture to an array of UIView s - without success.希望向UIView数组添加点击手势 - 没有成功。 Tap seems not to be recognised at this stage.在这个阶段似乎无法识别 Tap。

In the code (extract) below: Have a series of PlayingCardViews (each a UIView ) showing on the main view.在下面的代码(摘录)中: 在主视图上显示一系列PlayingCardViews (每个都是一个UIView )。 Brought together as an array: cardView .汇集为一个数组: cardView Need to be able to tap each PlayingCardView independently (and then to be able to identify which one was tapped).需要能够独立点击每个PlayingCardView (然后能够识别哪个被点击)。

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

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 循环中创建它

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

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.为了减少内存,您可以使用协议。 ex前任

    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 {
        
        weak 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)
        }
    }

I will not recommend the selected answer.我不会推荐所选的答案。 Because creating an array of tapGesture doesn't make sense to me in the loop.因为在循环中创建一个 tapGesture 数组对我来说没有意义。 Better to add gesture within PlaycardView.最好在 PlaycardView 中添加手势。

Instead, such layout should be designed using UICollectionView.相反,这种布局应该使用 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.如果您需要自定义布局并且想要使用 scrollView 甚至 UIView,那么更好的方法是创建单个 Gesture Recognizer 并添加到超级视图。

Using tap gesture, you can get the location of tap and then you can get the selectedView using that location.使用点击手势,您可以获得点击的位置,然后您可以使用该位置获取 selectedView。

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;
                }
            }

        }

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM