【问题标题】:How to get IndexPath for UICollectionView Header?如何获取 UICollectionView Header 的 IndexPath?
【发布时间】:2020-01-02 08:30:14
【问题描述】:

视图:页眉视图

class HeaderCell: UICollectionViewCell {
    //MARK: - Properties

....

    lazy var clearButton: UIButton = {
        let bt = UIButton(type: .custom)
        bt.backgroundColor = .clear
        bt.addTarget(self, action: #selector(handleClearButton(button:)), for: .touchUpInside)
        return bt
    }()

    weak var delegate: HeaderCellDelegate?

   //MARK: - Init
   required init?(coder aDecoder: NSCoder) {
        return nil
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        configureCell()
        addViews()
        setConstraints()
    }

....

    //MARK: - Handlers
    @objc func handleClearButton(button: UIButton) {
        delegate?.expandSelectedHeader(self)
    }

协议:HeaderCellDelegate

protocol HeaderCellDelegate: class {
    func expandSelectedHeader(_ header: UICollectionViewCell)
}

控制器:SomeController

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        switch kind {
        case UICollectionView.elementKindSectionHeader:
            let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: reuseIdentifierForHeader, for: indexPath) as! HeaderCell
            header.toMenuControllerDelegate = self
            return header

        case UICollectionView.elementKindSectionFooter:
            let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: reuseIdentifierForFooter, for: indexPath) as! MenuFooterCell
            return footer
        default:
            return UICollectionReusableView()
        }
    }


extension SomeController:HeaderCellDelegate {
    func expandSelectedHeader(_ header: UICollectionViewCell) {
        let indexPath = collectionView.indexPath(for: header)
        print(indexPath)
    }
}

我正在尝试在 headerView 中使用 clearButton,当点击按钮时,它会将自身(UIcollectionViewCell)发送到控制器。因此,一旦控制器接收到有关单元格的信息,我就可以使用collectionView.indexPath(for cell:UICollectionViewCell) 来获取点击按钮的标题的 indexPath。但是使用上面的代码,我只能得到nilprint(indexPath)

我该如何解决这个问题??? 我提前感谢您的帮助。

【问题讨论】:

    标签: ios swift uicollectionview


    【解决方案1】:

    您的委托函数expandSelectedHeader() 不知道它的indexPath,除非您将它传递给它。一种解决方法是在 HeaderCell 类中声明一个索引路径属性,并在创建补充视图时传递该值:

    class HeaderCell: UICollectionViewCell {
        //MARK: - Properties
        var indexPath: IndexPath?
       // rest of the code
    }
    
    //MARK: - Handlers
        @objc func handleClearButton(button: UIButton) {
            delegate?.expandSelectedHeader(self, indexPath: self.indexPath)
        }
    

    还要稍微修改一下协议:

    protocol HeaderCellDelegate: class {
        func expandSelectedHeader(_ header: UICollectionViewCell, indexPath: IndexPath?)
    }
    

    在创建视图时分配索引路径:

    // ...
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: reuseIdentifierForHeader, for: indexPath) as! HeaderCell
    // I'd suggest do not force down case the view as HeaderCell, use if..let
    header.toMenuControllerDelegate = self
    header.indexPath = indexPath
    // ...
    

    最后:

    extension SomeController:HeaderCellDelegate {
        func expandSelectedHeader(_ header: UICollectionViewCell, indexPath: IndexPath) {
            print(indexPath)
        }
    }
    

    【讨论】:

    • 感谢您对 Maysam 的评论,所以我们不能对标题单元格做这样的事情吗? stackoverflow.com/a/44368931/11530917
    • 重点是你的子类本质上并不知道它被分配到的索引路径。
    • 这就是为什么我要在func expandSelectedHeader(_ header: UICollectionViewCell) 中使用let indexPath = collectionView.indexPath(for: header) ??
    • 我猜它不适用于Supplementary View,但我不确定。
    【解决方案2】:

    而不是发送整个单元格然后获取索引路径。在协议中发送 IndexPath 并从中获取标头是一个好方法

    override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
      switch kind {
        case UICollectionElementKindSectionHeader:
            let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "header", for: indexPath) as! HeaderCollectionReusableView
            let gestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didSelectSection(gesture:)))
            headerView.addGestureRecognizer(gestureRecognizer)
            return headerView
        }
    }
    

    现在在 didSelectSection 中:

    @objc func didSelectSection(_ gestureRecognizer: UITapGestureRecognizer) {
        let indexPaths = self.collectionView?.indexPathsForVisibleSupplementaryElements(ofKind: UICollectionElementKindSectionHeader)
        for indexPath in indexPaths! {
            if (gestureRecognizer.view as! HeaderCollectionReusableView) == collectionView?.supplementaryView(forElementKind: UICollectionElementKindSectionHeader, at: indexPath){
                print("found at : \(indexPath)")
                break
            }
        }
    }
    

    【讨论】:

    • 在哪里可以找到 didSelectSection?你是说 didSelectItemAt 吗?
    • gesture.view 这是从哪里来的?
    • 它的gestureRecognizer.view ...抱歉忘记更改
    • 来自参数
    猜你喜欢
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    相关资源
    最近更新 更多