我正在尝试创建一个复杂的粘性UICollectionView标头:
y
位置时,标题会调整大小。现在事实证明这是一项挑战,但我取得了一些进展。为了简化问题,我首先创建一个标题,它将在滚动时调整大小并在触摸结束时保持其边界。
首先,我以最简单的形式创建了一个集合视图和补充视图标题:
private let defaultHeaderViewHeight: CGFloat = 250.0
private var beginHeaderViewHeight: CGFloat = defaultHeaderViewHeight
private var currentHeaderViewHeight: CGFloat = defaultHeaderViewHeight
private var headerView: HeaderView? {
get {
guard let headerView = collectionView?.supplementaryView(forElementKind: UICollectionElementKindSectionHeader, at: IndexPath(row: 0, section: 0)) as? HeaderView else { return nil }
return headerView
}
}
// Resizing logic
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
// Define the header size. This is called each time the layout is invalidated, and the beginHeaderViewHeight value is different each time
print("Header ref size delegate called, setting height to \(beginHeaderViewHeight)")
return CGSize(width: collectionView.frame.size.width, height: beginHeaderViewHeight)
// ^ super important!
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
currentHeaderViewHeight = max(0, -(collectionView?.contentOffset.y)! + beginHeaderViewHeight)
headerView?.frame.size.height = currentHeaderViewHeight
headerView?.frame.origin.y = collectionView?.contentOffset.y ?? 0
print("Did scroll\t\t\tcurrentHeaderViewHeight: \(currentHeaderViewHeight), content offset: \(scrollView.contentOffset.y)")
}
override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
print("Will end dragging\t\theader view frame height: \(headerView?.frame.size.height), content offset: \(scrollView.contentOffset.y)")
scrollView.bounds.origin = CGPoint(x: 0, y: 0)
self.collectionView?.collectionViewLayout.invalidateLayout()
print("Will end dragging\t\theader view frame height: \(headerView?.frame.size.height), content offset: \(scrollView.contentOffset.y)")
beginHeaderViewHeight = currentHeaderViewHeight
}
// Basic UICollectionView setup
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.register(UINib(nibName: "HeaderView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "Header View")
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 50
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
return cell
}
这种方法有效,但并非完全如此。当我向上滚动(触摸轨道向下)时,它的行为与我期望的一样 - 当触摸结束时,标题会调整大小并固定到位。这是一个用于验证的日志提取:
Did scroll currentHeaderViewHeight: 447.333333333333, content offset: -70.3333333333333
Did scroll currentHeaderViewHeight: 449.0, content offset: -72.0
Did scroll currentHeaderViewHeight: 451.0, content offset: -74.0
Did scroll currentHeaderViewHeight: 451.666666666667, content offset: -74.6666666666667
Will end dragging header view frame height: Optional(451.666666666667), content offset: -74.6666666666667
Will end dragging header view frame height: Optional(451.666666666667), content offset: 0.0
Did end dragging currentHeaderViewHeight: 451.666666666667, content offset: 0.0
Header ref size delegate called, setting height to 451.666666666667
但是,当我向下滚动(触摸向上)时,它会变得非常糟糕:看起来scrollViewDidScroll
被调用,even though I'm not setting the content offset anywhere:
Did scroll currentHeaderViewHeight: 330.666666666667, content offset: 121.0
Did scroll currentHeaderViewHeight: 330.333333333333, content offset: 121.333333333333
Did scroll currentHeaderViewHeight: 330.0, content offset: 121.666666666667
Did scroll currentHeaderViewHeight: 328.333333333333, content offset: 123.333333333333
Will end dragging header view frame height: Optional(328.333333333333), content offset: 123.333333333333
Will end dragging header view frame height: Optional(328.333333333333), content offset: 0.0
Did end dragging currentHeaderViewHeight: 328.333333333333, content offset: 0.0
Header ref size delegate called, setting height to 328.333333333333
// WHY ARE THESE LAST TWO LINES CALLED?
Did scroll currentHeaderViewHeight: 205.0, content offset: 123.333333333333
Did end deceler.. currentHeaderViewHeight: 205.0, content offset: 123.333333333333
所以tl;博士在这里:为什么当我向一个方向而不是另一个方向滚动时它是否有效?
奖励积分:如果有更清洁,更简单的方法来完成所有这些,请随时分享!