47

如何在顶部添加标题视图/顶视图(不是部分标题)UICollectionView

它应该完全作为UITableView' 的tableHeaderView财产。

所以它需要位于第一个部分标题视图的顶部(在索引 0 的部分之前),与其余内容一起滚动,并进行用户交互。

到目前为止,我想出的最好的方法是为第一部分标题视图制作一个特殊的 XIB(作为文件所有者的MyCollectionReusableView子类UICollectionReusableView),该视图大到足以在标题中包含我的子视图,这有点像黑客,我想想,我还没有设法检测到触摸。

不确定我是否可以让我的MyCollectionReusableView子类允许触摸或者有更好的方法。

4

7 回答 7

62
self.collectionView  =  [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 320, self.view.frame.size.height) collectionViewLayout:flowlayout];
self.collectionView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);
UIImageView *imagev = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"015.png"]];
imagev.frame = CGRectMake(0, -50, 320, 50);
[self.collectionView addSubview: imagev];
[self.view addSubview: _collectionView];

我使用该属性contentInset在顶部插入一个框架UICollectionView,然后将图像视图添加到它,它成功了。我认为它可以完全作为UITableView'tableHeaderView财产。你怎么看?

于 2013-08-02T11:31:53.803 回答
10

通过添加 UIView 作为集合视图的子视图,我将视图放在集合视图的顶部。它确实与集合视图一起向上滚动,并且具有正常的 UIView 用户交互。如果您没有节标题,这可以正常工作,但如果您这样做则不起作用。在那种情况下,我认为你的做法没有任何问题。我不确定你为什么没有检测到触摸,它们对我来说很好用。

于 2012-11-23T05:38:10.800 回答
6

由于 iOS 13 设置标题的规范方法是使用UICollectionViewCompositionalLayoutConfiguration

这种方式允许boundarySupplementaryItems按部分或全局设置集合视图。

let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(44))

let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: "header", alignment: .top)

let config = NSCollectionViewCompositionalLayoutConfiguration()
config.boundarySupplementaryItems = [header]

let layout = UICollectionViewCompositionalLayout(sectionProvider: sectionProvider, configuration: config)

return layout

要了解更多信息,请访问官方文档:https ://developer.apple.com/documentation/appkit/nscollectionviewcompositionallayoutconfiguration

于 2021-02-06T13:04:41.327 回答
5

我最终使用 UICollectionView 扩展来添加我的自定义标题。使用特定标签,我可以伪造存储的属性来识别我的自定义标头(从外部透明)。如果在添加自定义标题时 UICollectionView 的布局未完成,您可能必须滚动到特定偏移量。

extension UICollectionView {
    var currentCustomHeaderView: UIView? {
        return self.viewWithTag(CustomCollectionViewHeaderTag)
    }

    func asssignCustomHeaderView(headerView: UIView, sideMarginInsets: CGFloat = 0) {
        guard self.viewWithTag(CustomCollectionViewHeaderTag) == nil else {
            return
        }
        let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
        headerView.frame = CGRect(x: sideMarginInsets, y: -height + self.contentInset.top, width: self.frame.width - (2 * sideMarginInsets), height: height)
        headerView.tag = CustomCollectionViewHeaderTag
        self.addSubview(headerView)
        self.contentInset = UIEdgeInsets(top: height, left: self.contentInset.left, bottom: self.contentInset.bottom, right: self.contentInset.right)
    }

    func removeCustomHeaderView() {
        if let customHeaderView = self.viewWithTag(CustomCollectionViewHeaderTag) {
            let headerHeight = customHeaderView.frame.height
            customHeaderView.removeFromSuperview()
            self.contentInset = UIEdgeInsets(top: self.contentInset.top - headerHeight, left: self.contentInset.left, bottom: self.contentInset.bottom, right: self.contentInset.right)
        } 
    }
}

CustomCollectionViewHeaderTag 是指您提供给标题的标签号。确保它不是嵌入在 UICollectionView 中的 anotherView 的标签。

于 2018-03-02T21:08:50.717 回答
2

实现这一点的最佳方法是为第一部分制作一个部分标题。然后设置 UICollectionViewFlowLayout 的属性:

@property(nonatomic) BOOL sectionHeadersPinToVisibleBounds

或迅速

var sectionHeadersPinToVisibleBounds: Bool

为 NO(快速为 false)。这将确保节标题与单元格一起连续滚动,并且不会像节标题通常那样固定在顶部。

于 2016-01-06T06:32:21.683 回答
1

我认为最好的方法是将 UICollectionViewLayout(UICollectionViewFlowLayout) 子类化并添加所需的页眉或页脚属性。

由于 UICollectionView 布局中包括补充视图在内的所有项目都根据其collectionViewLayout属性collectionviewlayout决定是否存在页眉(页脚)。

使用contentInset起来更容易,但是当你想动态隐藏或显示标题时可能会出现问题。

我已经编写了一个协议来实现这一点,它可以被 UICollectionViewLayout 的任何子类采用,以使其具有页眉或页脚。你可以在这里找到它。

主要思想是为标题创建一个UICollectionViewLayoutAttributes并在layoutAttributesForElements(in rect: CGRect)需要时将其返回,您将必须修改所有其他属性,它们的所有位置都应向下移动标题高度,因为标题高于它们。

于 2017-09-01T02:35:14.390 回答
-2
private var PreviousInsetKey: Void?
extension UIView {

var previousInset:CGFloat {
    get {
        return objc_getAssociatedObject(self, &PreviousInsetKey) as? CGFloat ?? 0.0
    }
    set {
        if newValue == -1{
            objc_setAssociatedObject(self, &PreviousInsetKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        else{
            objc_setAssociatedObject(self, &PreviousInsetKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}


func addOnCollectionView(cv: UICollectionView){
    if self.superview == nil{
        var frame = self.frame
        frame.size.width = SCREEN_WIDTH
        cv.frame = frame
        self.addOnView(view: cv)
        let flow = cv.collectionViewLayout as! UICollectionViewFlowLayout
        var inset = flow.sectionInset
        previousInset = inset.top
        inset.top = frame.size.height
        flow.sectionInset = inset
    }

}

func removeFromCollectionView(cv: UICollectionView){
    if self.superview == nil{
        return
    }
    self.removeFromSuperview()
    let flow = cv.collectionViewLayout as! UICollectionViewFlowLayout
    var inset = flow.sectionInset
    inset.top = previousInset
    flow.sectionInset = inset
    previousInset = -1
}

func addOnView(view: UIView){

    view.addSubview(self)

    self.translatesAutoresizingMaskIntoConstraints = false
    let leftConstraint = NSLayoutConstraint(item: self, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0)
    let widthConstraint = NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: view.frame.size.width)
    let heightConstraint = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: view.frame.size.height)
    let topConstraint = NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 0)

    view.addConstraints([leftConstraint, widthConstraint, heightConstraint, topConstraint])
    self.layoutIfNeeded()
    view.layoutIfNeeded()
}
}
于 2017-06-06T09:42:34.750 回答