【问题标题】:iOS13 UICollectionViewFlowLayout subclass not receiving collectionView frame changesiOS13 UICollectionViewFlowLayout 子类不接收collectionView框架更改
【发布时间】:2019-10-09 00:52:28
【问题描述】:

我正在测试一些代码,看起来在 iOS13 中 UICollectionViewFlowLayout 没有收到 collectionView 框架中的更改。

下面是一个示例代码,其中我只是根据我在collectionView下方的tableview中滚动的量来改变collectionView的高度:

视图控制器

func scrollViewDidScroll(_ scrollView: UIScrollView) {  
    collectionView.collectionViewLayout.invalidateLayout()  

    let totalScroll = scrollView.contentSize.height - scrollView.bounds.size.height  
    let offset = (scrollView.contentOffset.y)  
    let percentage = offset / totalScroll  

    var frame = collectionView.frame  
    frame.size.height = 40 - (40 * percentage)  
    collectionView.frame = frame  
  }

CustomCollectionViewFlowLayout:UICollectionViewFlowLayout

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {  
    let attributes = super.layoutAttributesForElements(in: rect)  
    print(collectionView?.frame)  
    return attributes  
  }  

iOS 12 及以下版本的 CustomCollectionViewFlowLayout 中的打印语句正确打印出 collectionView.frame 中的更改,即高度实际更改。但在 iOS 13 中,它根本没有体现出来。

帮助任何人?

【问题讨论】:

标签: swift uicollectionview ios13 flowlayout


【解决方案1】:

首先,

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    collectionView.collectionViewLayout.invalidateLayout()
    ...
}

看起来很可疑。您确定您的布局应该在 scrollViewDidScroll 函数中失效吗?

有一个适当的地方应该在滚动时使布局失效:

final class CustomCollectionViewFlowLayout: UICollectionViewFlowLayout {

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        // proper place to invalidate layout while scrolling
    }
}

如果您在布局类中使布局无效,您将能够正确计算所需的布局容器高度。然后你可以通知你的集合视图它的高度应该改变。例如,在一些代表的帮助下:

protocol CustomCollectionViewFlowLayoutSizeDelegate: class {

    func newSizeAvailableFor(layout: CustomCollectionViewFlowLayout, progress: CGFloat)
}

final class CustomCollectionViewFlowLayout: UICollectionViewFlowLayout {

    weak var sizeDelegate: CustomCollectionViewFlowLayoutSizeDelegate?

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        // proper place to invalidate layout while scrolling
    }
}

final class CustomViewController: CustomCollectionViewFlowLayoutSizeDelegate {

    func newSizeAvailableFor(layout: CustomCollectionViewFlowLayout, progress: CGFloat) {
        // change collectionView frame
    }
}

结论:

您的布局正在尝试侦听其容器高度,但其容器高度是根据您的布局计算得出的。您可以轻松地删除容器依赖项以进行高度计算,或者只为布局提供初始容器高度。最终布局将负责所有的计算。

【讨论】:

  • 原来的解决方案是直接使用 view.layer.frame 而不是 view.frame。其余代码保持不变:)
  • @Karthik 好吧......在特定情况下它可能是一个解决方案。但是,找到更通用的方法总是一个好方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
  • 1970-01-01
  • 2018-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多