我正在尝试实现一个自定义顶部栏,其行为类似于iOS 11+的大标题导航栏,当向下滚动内容时,栏的大标题部分会折叠:
我的需求是定制高度的导航栏,并且滚动时底部部分不会折叠。我已经成功实现了这个部分。 使用UIStackView实现了该条,同时添加了一些非必需的布局约束,但我认为其内部实现并不重要。最重要的是该条的高度与scrollview的顶部contentInset相关联。这些由scrollview的contentOffset在UIScrollViewDelegate.scrollViewDidScroll方法中驱动:func scrollViewDidScroll(_ scrollView: UIScrollView) {
let topInset = (-scrollView.contentOffset.y).limitedBy(topBarHeightRange)
// changes both contentInset and scrollIndicatorInsets
adjustTopContentInset(topInset)
// changes top bar height
heightConstraint?.constant = topInset
adjustSmallTitleAlpha()
}
topBarHeightRange
存储了导航栏高度的最小值和最大值。
我遇到的一个问题是,当用户停止滚动 scrollview 时,导航栏可能会处于半折叠状态。再次看一下期望的行为:
内容偏移量被捕捉到更接近的紧凑或展开高度。我正在尝试在 UIScrollViewDelegate.scrollViewWillEndDragging
方法中实现相同的效果:
func scrollViewWillEndDragging(_ scrollView: UIScrollView,
withVelocity velocity: CGPoint,
targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let targetY = targetContentOffset.pointee.y
// snaps to a "closer" value
let snappedTargetY = targetY.snappedTo([topBarHeightRange.lowerBound, topBarHeightRange.upperBound].map(-))
targetContentOffset.pointee.y = snappedTargetY
print("Snapped: \(targetY) -> \(snappedTargetY)")
}
效果远非完美:
![My custom bar details](https://istack.dev59.com/k5034.gif)
targetContentOffset
被正确修改。然而,在应用程序中,视觉上内容偏移仅捕捉到紧凑高度,而不是扩展高度(您可以观察到大的“标题”标签最终被切成两半,而不是回到“扩展”位置)。我怀疑这个问题与在用户滚动时更改
contentInset.top
有关,但我无法弄清楚如何修复此行为。有点难以解释问题,所以希望GIF能够帮助。这是存储库:https://github.com/AleksanderMaj/ScrollView 有什么想法可以使scrollview/bar组合正确地捕捉紧凑/扩展高度吗?