Прежде всего,
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
}
}
Вывод:
Ваш макет пытается прослушать высоту своего контейнера, но высота его контейнера рассчитывается на основе вашего макета. Вы можете легко удалить зависимость контейнера для расчета высоты или просто предоставить макету начальную высоту контейнера. В конце концов макет будет отвечать за все расчеты.