简体   繁体   中英

How to add gesture for a view inside a collection view cell?

I am adding a view having set of images(socialView) inside a collection view cell(having other views also) on which a common click has to be performed. This click should not be same as collection view cell click.

I am thinking of adding UITapGestureRecognizer for socialView everytime in CollectionView delegate method cellForItemAt . But I want to know is it the right way? Moreover, i want to get the indexPath/position on which socialView has been called.

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.socialViewTapped))

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "bidderAuctionCell", for: indexPath) as! BidderAuctionViewCell
     cell.socialView.addGestureRecognizer(tapGestureRecognizer)
}

@objc func socialViewTapped() {
     // Which item cell's socialview is clicked
}

UPDATE

I have done as per the below suggestions, but i am not able to get where should i add UITapGestureRecognizer in the custom cell. Following is the custom cell which i have created.

class CustomViewCell: UICollectionViewCell {

    var index : IndexPath!
    var socialViewDelegate : SocialViewDelegate!

    @IBOutlet weak var socialView: UIView!

    override init(frame: CGRect) {
        super.init(frame:frame)
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action:   #selector(self.viewTapped))
        socialView.addGestureRecognizer(tapGestureRecognizer)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder:aDecoder)
    }

    @objc func viewTapped(){
        socialViewDelegate.socialViewTapped(at: index)
    }
}

The init function is not being called. I also tried to put in required init, but there the social view is not initialized. So getting crashed

FINAL ANSWER

class CustomViewCell: UICollectionViewCell {

    var index : IndexPath!
    var socialViewDelegate : SocialViewDelegate!

    @IBOutlet weak var socialView: UIView!

    override func awakeFromNib() {
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        socialView.isUserInteractionEnabled = true
        socialView.addGestureRecognizer(tapGesture)
    }

    @objc func handleTap(){
        socialViewDelegate.socialViewTapped(at: index)
    }
}
protocol SocialViewDelegate {
    func socialViewTapped(at index: IndexPath)
}

@Anurag you can solve this problem by using either of the following concepts Delegation, Closures, Notifications. I will suggest you go with the delegation pattern which iOS follows widely into its components like UITableView, UICollectionView etc.

  • Before implementing the delegation pattern add a tap gesture recognizer to the view.
  • In CollectionViewCell declare a protocol method to delegate your tap/action
  • Confirm delegate implementation in your view controller.
  • Implement your delegated method in your view controller.

Coding Example:

1. Your CollectionViewCell should look like this :

   import UIKit

    Protocol ViewTappedDelegate: class {
     func viewTapped(_ photo : String) { }
   }

    class YourCell: UICollectionViewCell, UIGestureRecognizerDelegate {

        @IBOutlet weak var containerView: UIView!
        weak var delegate : ViewTappedDelegate?

        override func awakeFromNib() {
            let tapGesture = UITapGestureRecognizer(target: self,
                                                    action: #selector(handleTap(recognizer:)))
            tapGesture.delegate = self
            containerView.isUserInteractionEnabled = true
            containerView.addGestureRecognizer(tapGesture)
        }

        @objc func handleTap(recognizer:UITapGestureRecognizer) {
            //Call Delegate method from here...
        }

    }

2. In ViewController

        func collectionView(_ collectionView: UICollectionView,
                    cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {


               let cell =  collectionView.dequeueReusableCell(withReuseIdentifier: "cellIdentifier",
                                                  for: indexPath) as! YourCell

              cell.delegate = self
              return cell
          }



    // MARK: Delegate
     extension YourViewController : ViewTappedDelegate {
        func viewTapped(_ photo : String) {
          // Handle delegation here...
        }
    }

In order to add tap gesture please add the following code into the cell of your collection view.

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.socialViewTapped))
socialView?.addGestureRecognizer(tapGestureRecognizer)
socialView?.isUserInteractionEnabled = true

Add this code to the collection view cell.

I hope this works if you still haven't find a way you use protocol like this, in your custom cell like this

import UIKit

protocol CustomDelegate {
    func showData(indexPath: IndexPath?)
}

class CustomCell: UICollectionViewCell {

// properties

var delegate: CustomDelegate?
var selectedAtIndex: IndexPath?

// outlets

override func awakeFromNib() {
    super.awakeFromNib()
    myView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dothis)))
}

@objc func dothis(){
    delegate?.showData(indexPath: selectedAtIndex)
}

@IBOutlet weak var myView: UIView!
}

write your view controller like this

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, CustomDelegate{
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
    cell.delegate = self
    cell.selectedAtIndex = indexPath
    return cell
}
func showData(indexPath: IndexPath?) {
    if let ip = indexPath{
            print("\(ip) is the index path for tapped view")
    }
}
}

do tell if this helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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