使用UICollectionViewFlowLayoutAutomaticSize的iOS 10/11 UICollectionViewFlowLayout导致页脚补充视图未对齐 [英] iOS 10/11 UICollectionViewFlowLayout using UICollectionViewFlowLayoutAutomaticSize results in footer supplementary view misaligned
问题描述
所以这是一个有趣的问题,我们在iOS 10上找到了 UICollectionViewFlowLayout
(仍然是11的问题)并使用 UICollectionViewFlowLayoutAutomaticSize
for estimateItemSize。
So this is an interesting issue we found with UICollectionViewFlowLayout
on iOS 10 (still an issue on 11) and using UICollectionViewFlowLayoutAutomaticSize
for the estimatedItemSize.
我们发现在页脚补充视图中使用 UICollectionViewFlowLayoutAutomaticSize
获取estimatedItemSize结果漂浮在底部几个单元格之上。(红色/粉红色是标题,绿色是页脚。)
We've found that using UICollectionViewFlowLayoutAutomaticSize
for the estimatedItemSize results in the footer supplementary view floating above the bottom few cells.(Red/Pink is the header, Green is the footer.)
< a href =https://i.stack.imgur.com/0fAt7.png =noreferrer>
以下是示例应用的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上工作?如果我在estimatedItemSize中添加一个大小,那么它似乎可以工作,但我想知道使用新的iOS 10功能是否存在错误,或者我是否使用错误。
Has anyone managed to get UICollectionViewFlowLayoutAutomaticSize to work on iOS 10 with supplementary header and footer views? If I add a size to the estimatedItemSize then it appears to work, but I want to know if there is a bug in using the new iOS 10 feature or if I'm using it incorrectly.
向Apple提交的错误ID为: 28843116
The bug filed with Apple has the ID: 28843116
更新:这仍然显示为是10.3 Beta 1的问题
UPDATE: This still appears to be an issue on 10.3 Beta 1
更新2 :这仍然是iOS 11 Beta 1中的一个问题
UPDATE 2: This still appears to be an issue in iOS 11 Beta 1
推荐答案
UICollectionViewFlowLayout
支持细胞的自动布局,但它不支持补充意见。每次自动布局代码更新单元格的框架时,它都不会对页眉和页脚做任何处理。因此,您需要告诉布局它应该使页眉和页脚无效。并且有一种方法可以做到这一点!
UICollectionViewFlowLayout
supports auto layout for cells very well, BUT it does not supports it for supplementary views. Each time when auto layout code updates cell's frame it does nothing with headers and footers. So you need to tell layout that it should invalidate headers and footers. And there is a method for this!
你应该覆盖 UICollectionViewLayout
的 func invalidationContext(forPreferredLayoutAttributes:UICollectionViewLayoutAttributes,withOriginalAttributes:UICollectionViewLayoutAttributes )
并在其中执行补充视图无效。
You should override UICollectionViewLayout
's func invalidationContext(forPreferredLayoutAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes: UICollectionViewLayoutAttributes)
and perform supplementary view invalidation in it.
示例:
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 <提供的失效上下文/ code>如果节中的第一个单元格无效,则使标题补充视图无效。您也可以将此方法用于页脚失效。
In example above I am using invalidation context provided by UICollectionViewFlowLayout
to invalidate header supplementary view if first cell in section was invalidated. You can use this method for footer invalidation as well.
这篇关于使用UICollectionViewFlowLayoutAutomaticSize的iOS 10/11 UICollectionViewFlowLayout导致页脚补充视图未对齐的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!