UICollectionView:将单击手势识别器添加到补充视图

Posted

技术标签:

【中文标题】UICollectionView:将单击手势识别器添加到补充视图【英文标题】:UICollectionView: Adding single Tap Gesture Recognizer to supplementary view 【发布时间】:2013-10-01 20:05:49 【问题描述】:

我有一个带有补充视图的 UICollectionView ——本质上是集合的标题。每当我使用界面生成器将手势识别器添加到 headerView.xib 中的 UILabel 时,应用程序崩溃给我

*** 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'

是什么阻止我在 UICollectionView 的补充视图中向 UILabel 添加手势识别器?

【问题讨论】:

我已指定重新开放的问题。从目前收到的重新开放投票来看,它应该很快就会重新开放。如果发生这种情况,请将您的解决方案作为答案发布。这将有助于未来的读者:) 我也看到了同样的问题。我可以通过以编程方式添加手势识别器继续前进,但我也想知道为什么使用 Interface Builder 不起作用。 【参考方案1】:

所以看起来您不能使用界面构建器将手势识别器添加到 UICollectionView 的补充视图中。

我相信这是因为当加载 .xib 时,UICollectionView 必须作为一件事出现在超级视图中——当您将手势识别器添加到该 UICollectionView 时,您最终会在超级视图级别得到两件事,这两者对应UICollectionView。

但是,您可以使用 UICollectionViewReusableView 协议内的补充视图定义以编程方式实现手势识别器。 (if 用于在代码后面区分页眉补充视图和页脚补充视图)

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;

【讨论】:

【参考方案2】:

我也无法通过 IB 向单元格添加手势。

但是,我的经验是,使用 IB,您可以通过将手势识别器拖到大纲视图中的 collectionView 项目而不是图形表示中位于 collectionView 顶部的 scrollView 来将手势识别器添加到 collectionView 本身。

到目前为止,我只能在单元格中单击一下并进入 collectionView。

【讨论】:

【参考方案3】:

当从 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()
     

【讨论】:

【参考方案4】:

如何在 nib 加载后以编程方式添加它?或者,在 IB 中,您是否尝试过将代表识别器的图标的位置移动到代表视图的图标的上方或下方

【讨论】:

与手势识别器有关。也就是说,使用 IB 将手势识别器添加到 .xib 会导致此错误。 如何在笔尖加载后以编程方式添加它?或者,在 IB 中,您是否尝试过将代表识别器的图标的位置移动到代表视图的上方或下方。 就是这样。感谢您的意见。 我更新了答案以反映有效的方法:请投票。

以上是关于UICollectionView:将单击手势识别器添加到补充视图的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 单元格和按钮

带有手势识别器的 UICollectionView

手势识别器在其他 UICollectionViewCell 内的 UICollectionView 上不起作用

具有 UIView 作为子视图的 UICollectionView 的选择性手势识别

UICollectionView的选择性手势识别,UIView为子视图

UICollectionView 的 didSelectItemAtIndexPath 仅在用两根手指选择单元格时调用