Подтвердить что ты не робот

Как добавить HeaderView в UICollectionView, например UITableView tableHeaderView

Как добавить заголовок/верхний вид (не заголовок раздела) в верхней части UICollectionView?

Он должен действовать как свойство UITableView tableHeaderView.

Поэтому он должен сидеть поверх первого заголовка раздела (перед секцией с индексом 0), прокручивать вместе с остальной частью содержимого и взаимодействовать с пользователем.

Лучшее, что я до сих пор придумал, - создать специальный XIB (с подклассом MyCollectionReusableView UICollectionReusableView в качестве владельца файла) для первого заголовка заголовка, который достаточно велик, чтобы также содержать мои подпрограммы в заголовок, это вроде хак, я думаю, и мне не удалось обнаружить прикосновения.

Не уверен, могу ли я сделать мой подкласс MyCollectionReusableView, чтобы разрешить касания или там лучший способ.

4b9b3361

Ответ 1

Я поставил представление в верхней части коллекции, просто добавив UIView в качестве подзадача представления коллекции. Он просматривает просмотр коллекции и имеет обычное пользовательское взаимодействие UIView. Это работает нормально, если у вас нет заголовка раздела, но он не работает, если вы это сделаете. В этой ситуации я не вижу ничего плохого в том, как вы это делаете. Я не уверен, почему вы не обнаруживаете прикосновений, они отлично работают для меня.

Ответ 2

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. Как вы думаете?

Ответ 3

Лучший способ добиться этого - сделать заголовок раздела для первого раздела. Затем установите свойство UICollectionViewFlowLayout:

@property(nonatomic) BOOL sectionHeadersPinToVisibleBounds

или быстро

var sectionHeadersPinToVisibleBounds: Bool

до NO (false для быстрого). Это гарантирует, что заголовок секции непрерывно прокручивается с ячейками и не привязывается к вершине, как обычно, заголовок секции.

Ответ 4

Я думаю, что лучший способ выполнить это для подкласса UICollectionViewLayout (UICollectionViewFlowLayout) и добавить необходимые атрибуты верхнего или нижнего колонтитула.

Поскольку все элементы, включая дополнительный вид в макете UICollectionView, в соответствии с его свойством collectionViewLayout, это collectionViewLayout, который определяет, есть ли заголовок (нижний колонтитул) или нет.

Использовать contentInset проще, но может возникнуть проблема, когда вы хотите скрыть или показать заголовок динамически.

Я написал протокол для этого, который может быть принят любым подклассом UICollectionViewLayout, чтобы он имел верхний или нижний колонтитул. Вы можете найти здесь.

Основная идея состоит в том, чтобы создать UICollectionViewLayoutAttributes для заголовка и вернуть его в layoutAttributesForElements(in rect: CGRect), если потребуется, вам придется изменить все остальные атрибуты, все их местоположения должны быть перемещены вниз по высоте заголовка, потому что заголовок выше всех.

Ответ 5

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