IOS 10/11 UICollectionViewFlowLayout с использованием UICollectionViewFlowLayoutAutomaticSize приводит к уменьшению нижнего колонтитула
Итак, это интересная проблема, которую мы обнаружили с помощью UICollectionViewFlowLayout
на iOS 10 (по-прежнему проблема 11) и с помощью UICollectionViewFlowLayoutAutomaticSize
для оцененногоItemSize.
Мы обнаружили, что использование UICollectionViewFlowLayoutAutomaticSize
для оценочного результата в примере ItemSize в дополнительном представлении нижнего колонтитула, плавающего над нижними немногими ячейками. (Красный/Розовый - это заголовок, зеленый - нижний колонтитул.)
![введите описание изображения здесь]()
Вот код 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 {
}
Кто-нибудь смог получить UICollectionViewFlowLayoutAutomaticSize для работы с iOS 10 с дополнительными представлениями верхнего и нижнего колонтитулов? Если я добавлю размер в sampleItemSize, то он работает, но я хочу знать, есть ли ошибка в использовании новой функции iOS 10 или если я неправильно ее использую.
Ошибка, поданная с Apple, имеет идентификатор: 28843116
ОБНОВЛЕНИЕ. Это все еще кажется проблемой в 10.3 Beta 1
ОБНОВЛЕНИЕ 2. Это все еще кажется проблемой в iOS 11 Beta 1
Ответы
Ответ 1
UICollectionViewFlowLayout
очень хорошо поддерживает автоматический макет для ячеек, НО, он не поддерживает его для дополнительных просмотров. Каждый раз, когда auto layout code обновляет ячейку кадра, он ничего не делает с верхними и нижними колонтитулами. Поэтому вам нужно сообщить макет, что он должен аннулировать верхние и нижние колонтитулы. И есть способ для этого!
Вы должны переопределить UICollectionViewLayout
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
Я столкнулся с той же проблемой. UICollectionViewFlowLayoutAutomaticSize
не работает для дополнительных просмотров. Используйте UICollectionViewDelegateFlowLayout
, чтобы указать размер явно. Лучше рассчитать размеры и использовать делегатов, поскольку автоматические вычисления размера иногда задерживаются.
используйте методы referenceSizeForHeaderInSection
и referenceSizeForFooterInSection
делегирования, чтобы явно указать размер заголовка и нижнего колонтитула.