如何像UITableView的tableHeaderView一样在UICollectionView中添加HeaderView

我怎样才能在UICollectionView的顶部添加一个标题视图/顶视图(不是部分标题)?

它应该充当UITableViewtableHeaderView属性。

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

到目前为止我所得到的最好的结果是为第一个节头视图创build一个特殊的XIB(使用MyCollectionReusableView子类作为文件的所有者),这个视图的大小足以在头中包含我的子视图,这是一种黑客,我想,我还没有设法检测到触摸。

不知道如果我可以让我的MyCollectionReusableView子类允许触摸或有更好的方法。

我只是通过添加一个UIView作为集合视图的子视图,将一个视图放在集合视图的顶部。 它向上滚动的集合视图,它有正常的UIView用户交互。 这工作正常,如果你没有部分标题,但不工作,如果你这样做。 在这种情况下,我看不出你做这件事的方式有什么问题。 我不知道为什么你没有检测到触摸,他们工作正常。

 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的顶部,然后我添加图像视图,并成功。 我认为它可以作为UITableViewtableHeaderView属性excactly。 你怎么看?

实现这一目标的最好方法是为第一部分创build一个部分标题。 然后设置UICollectionViewFlowLayout的属性:

 @property(nonatomic) BOOL sectionHeadersPinToVisibleBounds 

或迅速

 var sectionHeadersPinToVisibleBounds: Bool 

到NO(快速为false)。 这将确保节标题与单元格连续滚动,而不像段标题那样固定在顶部。

我认为最好的办法来完成这个子类UICollectionViewLayout(UICollectionViewFlowLayout)并添加所需的页眉或页脚属性。

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

使用contentInset比较容易,但是当您想要dynamic地隐藏或显示标题时可能会出现问题。

我已经写了一个协议来完成这个任务,可以通过UICollectionViewLayout的任何子类来使它有一个页眉或页脚。 你可以在这里find它。

主要的想法是为header创build一个UICollectionViewLayoutAttributes并在layoutAttributesForElements(in rect: CGRect)返回它,如果需要的话,你将不得不修改所有其他的属性,所有的位置都应该被header高度向下移动,因为header是在他们之上。

 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() } }