Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView: Adding single Tap Gesture Recognizer to supplementary view

I have a UICollectionView with a supplementary view -- in essence a header for the collection. Whenever I add a gesture recognizer to a UILabel within the headerView.xib using the interface builder, the app crashes giving me

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'invalid nib registered for identifier (MY_HEADER) - nib must contain exactly one top level object which must be a UICollectionReusableView instance'

What is preventing me from adding a gesture recognizer to a UILabel within a supplementary view of a UICollectionView?

like image 389
conner.xyz Avatar asked Oct 01 '13 20:10

conner.xyz


People also ask

How to add the tap gesture recognizer to imageview in Android?

In the viewDidLoad () method, we invoke addGestureRecognizer (_:) on imageView, passing in the tap gesture recognizer, to add the tap gesture recognizer to imageView. Let's build and run the application to make sure the image view still responds to taps. Tap the image view and press Command + Shift + Y to inspect the output in the console.

How do I rearrange items in a uicollectionviewcontroller?

The UICollectionViewController class provides a default gesture recognizer that you can use to rearrange items in its managed collection view. To install this gesture recognizer, set the installsStandardGestureForInteractiveMovement property of the collection view controller to true.

How do I add a gesture recognizer to my interface?

I always add gesture recognizers in code, but that is a personal choice. Let's start with Interface Builder. Open Main.storyboard and drag a tap gesture recognizer from the Object Library and drop it onto the image view we added earlier. The tap gesture recognizer appears in the Document Outline on the left.

How do I add a supplementary view to a collection view?

By implementing the method, you provide a supplementary view to display in the collection view. First, download the header/footer background images and add them into the Xcode project. Go back to Storyboard. Select “Collection View” of the Collection View controller.


2 Answers

I add gesture recognizer when the supplementary view has been loaded from nib.

class MySuppleMentaryView: UICollectionReusableView
{

    @IBOutlet var label: UILabel!

    weak var delegate: MySuppleMentaryViewDelegate!

    override func awakeFromNib() {
        super.awakeFromNib()

        // NOTE: UILabel MUST enable user interaction to receive touch events.
        // label.isUserInteractionEnabled = true

        let tap = UITapGestureRecognizer(target: self, action: #selector(onClickLabel))
        tap.delaysTouchesBegan = true
        tap.numberOfTapsRequired = 1

        self.label.addGestureRecognizer(tap)
    }

    @objc func onClickLabel() {
        self.delegate.didOnLabel(cell: self)
    }
}

protocol MySuppleMentaryViewDelegate: NSObjectProtocol {
    func didOnLabel(cell: DCScheduleHourLabel)
}

// Configure supplementary cell
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

    if (kind == UICollectionElementKindSectionHeader) { 
        // NOTE: The cell might be reused.
        // If gesture recognizer is added HERE, 
        // then maybe multiple gesture recognizers are added when reusing the cell. 
        let cell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: DCScheduleDummyBlock.Identifier, for: indexPath) as! MySuppleMentaryView

        // configure cell
        cell.delegate = self
        return cell                
    }

    return UICollectionReusableView()
}     
like image 198
AechoLiu Avatar answered Sep 30 '22 10:09

AechoLiu


So it looks like you cannot use the interface builder to add a gesture recognizer to a supplementary view of a UICollectionView.

I believe this is because when the .xib's are loaded, the UICollectionView must appear as one thing to the superview -- and when you add the gesture recognizer to that UICollectionView you end up with two things at the superview level, which both correspond to the UICollectionView.

You can however implement your gesture recognizer programmatically using the definition of your supplementary view inside of the UICollectionViewReusableView Protocol. (The if is being used to distinguish between a header supplementary view and an footer supplementary view later in the code)

if (kind == UICollectionElementKindSectionHeader) {
    MyHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"MY_HEADER" forIndexPath:indexPath];

    // call headerView methods (to put things into the header's UI objects for example)
    [headerView ...];
    [headerView ...];
    [headerView ...];

    // add gesture recognition for tapping on a UIlabel within the header (UICollectionView supplementary view)
    UITapGestureRecognizer *bioTap = [[UITapGestureRecognizer alloc] initWithTarget:headerView action:@selector(handleUILabelTap:)];
    // make your gesture recognizer priority
    bioTap.delaysTouchesBegan = YES;
    bioTap.numberOfTapsRequired = 1;
    [headerView.UILabelName addGestureRecognizer:UILabelTap];

    reusableview = headerView;
}
like image 35
conner.xyz Avatar answered Sep 30 '22 10:09

conner.xyz