2016-10-19 4 views
16

Так что это интересный вопрос, который мы нашли с UICollectionViewFlowLayout на прошивке 10 (до сих пор вопрос 11) и используя UICollectionViewFlowLayoutAutomaticSize для estimatedItemSize.IOS 10/11 UICollectionViewFlowLayout с использованием результатов UICollectionViewFlowLayoutAutomaticSize в колонтитуле дополнительного зрения смещено

Мы обнаружили, что использование UICollectionViewFlowLayoutAutomaticSize для результатов estimatedItemSize в колонтитуле дополнительного зрении плавающего выше дно нескольких клеток. (Красный/Розовый заголовок, Зеленый футер.)

UICollectionViewFlowLayoutAutomaticSize problem enter image description here

Вот VC код из примера приложения:

import UIKit 

class ViewController: UIViewController { 

    // MARK: Properties 

    let texts: [String] = [ 
     "This is some text", 
     "This is some more text", 
     "This is even more text" 
    ] 

    // MARK: Outlets 

    @IBOutlet var collectionView: UICollectionView! { 
     didSet { 
      self.collectionView.backgroundColor = .orange 
     } 
    } 

    // MARK: Lifecycle 

    override func viewDidLoad() { 

     super.viewDidLoad() 

     // Layout 
     let layout = UICollectionViewFlowLayout() 
     layout.scrollDirection = .vertical 
     if #available(iOS 10.0, *) { 
      layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize 
     } else { 
      layout.estimatedItemSize = CGSize(width: self.collectionView.bounds.width, height: 50) 
     } 
     self.collectionView.collectionViewLayout = layout 

     // Register Cells 
     self.collectionView.register(UINib(nibName: "TextCell", bundle: nil), forCellWithReuseIdentifier: String(describing: TextCell.self)) 
     self.collectionView.register(UINib(nibName: "SectionHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: String(describing: SectionHeader.self)) 
     self.collectionView.register(UINib(nibName: "SectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: String(describing: SectionFooter.self)) 

     self.collectionView.reloadData() 
    } 
} 

// MARK: - UICollectionViewDelegateFlowLayout Methods 

extension ViewController: UICollectionViewDelegateFlowLayout { 

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { 

     return CGSize(width: self.collectionView.bounds.width, height: 90) 
    } 

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { 

     return CGSize(width: self.collectionView.bounds.width, height: 90) 
    } 
} 

// MARK: - UICollectionViewDataSource Methods 

extension ViewController: UICollectionViewDataSource { 

    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 

     return self.texts.count 
    } 

    func numberOfSections(in collectionView: UICollectionView) -> Int { 
     return 1 
    } 

    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 

     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: TextCell.self), for: indexPath) 

     if let textCell = cell as? TextCell { 

      let text = self.texts[indexPath.row] 
      textCell.configure(text: text) 
     } 

     return cell 
    } 

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 

     switch kind { 
     case UICollectionElementKindSectionHeader: 

      return collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: String(describing: SectionHeader.self), for: indexPath) 

     case UICollectionElementKindSectionFooter: 

      return collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: String(describing: SectionFooter.self), for: indexPath) 

     default: 
      return UICollectionReusableView() 
     } 
    } 
} 

// MARK: - UICollectionViewDelegate Methods 

extension ViewController: UICollectionViewDelegate { 

} 

кто-нибудь удалось получить UIColle ctionViewFlowLayoutAutomaticSize для работы с iOS 10 с дополнительными представлениями верхнего и нижнего колонтитулов? Если я добавлю размер в оценочныйItemSize, то он работает, но я хочу знать, есть ли ошибка при использовании новой функции iOS 10 или если я использую ее неправильно.

Буга поданную Apple, имеет ID:

UPDATE: Это по-прежнему, как представляется, вопрос о 10.3 Beta 1

UPDATE 2: Это по-прежнему, как представляется, выпуск в iOS 11 Бета 1

+0

Вам необходимо предоставить оценочный ариф. Он не является обязательным – Lefteris

+0

Он устанавливается, он просто отличается от IOS 10 и раньше. – dlbuckley

+0

Вы нашли решение для этого? –

ответ

0

Я столкнулся с той же проблемой. UICollectionViewFlowLayoutAutomaticSize не подходит для дополнительных просмотров. Используйте UICollectionViewDelegateFlowLayout, чтобы указать размер явно. Лучше рассчитать размеры и использовать делегатов, поскольку автоматические расчеты размеров иногда заставляют отставать.

использовать referenceSizeForHeaderInSection и referenceSizeForFooterInSection методы делегата, чтобы явно указать размер заголовка и нижнего колонтитула.

+0

Спасибо за ввод.Хотя, если вы посмотрите на код, который я разместил, я использую методы делегата 'referenceSizeForHeaderInSection' и' referenceSizeForFooterInSection', чтобы установить высоту в 90 точек. Или вы имеете в виду что-то еще? – dlbuckley

+0

Код в порядке. Удалите эту часть и попробуйте присвоить размер pf клеткам с помощью вычислений. ', если #available (IOS 10.0, *) { layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize } еще { layout.estimatedItemSize = CGSize (ширина: self.collectionView.bounds.width, высота: 50) }' –

+0

Он работает, если Я не использую 'UICollectionViewFlowLayoutAutomaticSize', но все дело в том, чтобы понять, как работает UICollectionViewFlowLayoutAutomaticSize'. Наше решение переместило автоматическую калибровку в конце так же, как и ваше предложение, но было бы неплохо использовать автоматическую калибровку в будущем. – dlbuckley

14

UICollectionViewFlowLayout поддерживает автоматическую компоновку для ячеек очень хорошо, НО НОТА не поддерживает его для дополнительных просмотров. Каждый раз, когда код автоматического макета обновляет фрейм ячейки, он ничего не делает с верхними и нижними колонтитулами. Поэтому вам нужно сообщить макет, что он должен аннулировать верхние и нижние колонтитулы. И есть способ для этого!

Вы должны переопределить UICollectionViewLayout's func invalidationContext(forPreferredLayoutAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes: UICollectionViewLayoutAttributes) и выполнить в нем недействительность дополнительного вида.

Пример:

override open func invalidationContext(forPreferredLayoutAttributes preferred: UICollectionViewLayoutAttributes, 
     withOriginalAttributes original: UICollectionViewLayoutAttributes) 
       -> UICollectionViewLayoutInvalidationContext { 
    let context: UICollectionViewLayoutInvalidationContext = super.invalidationContext(
      forPreferredLayoutAttributes: preferred, 
      withOriginalAttributes: original 
    ) 

    let indexPath = preferred.indexPath 

    if indexPath.item == 0 { 
     context.invalidateSupplementaryElements(ofKind: UICollectionElementKindSectionHeader, at: [indexPath]) 
    } 

    return context 
} 

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

+2

Это решило проблему для меня. Вдруг мои заголовки были правильно расположены. – MurderDev

+0

В свою очередь, мне нужно также аннулировать ячейку внутри области 'if', вызывая' context.invalidateItems (at:) '. – billibala