由于您使用的内容是可滚动的,因此您应该使用某种形式的滚动视图来执行此操作。有几种方法可以做到这一点:
- 直接在滚动视图上添加视图
- 使用垂直堆栈视图在滚动视图上布局视图
- 使用
UITableView(是滚动视图的子类)
- 使用
UICollectionView(是滚动视图的子类)
在任何情况下,您都应该将delegate 分配给您使用的滚动视图。通过这样做,您可以通过实现可选协议方法scrollViewDidScroll 来跟踪滚动视图偏移量的变化。根据滚动视图内容的偏移量,您可以选择折叠或扩展标题。
标题本身可以在滚动视图上,但我建议您将其放在上面。您可以简单地将其限制在顶部,并具有等于或大于段控件高度的完整优先级高度。然后有另一个低优先级的高度约束(优先级应该是 900),它可以作为出口拖到你的代码中。有多种方法可以实现这一点,这样做应该会产生类似于
的代码
func scrollViewDidScroll(_ scrollView: UIScrollView) {
headerMaximumHeightConstraint?.constant = collapsableHeaderMaximumHeight-scrollView.contentOffset.y
}
这将使您的标题在用户向下拖动和折叠向上拖动时扩展。由于此约束的优先级低于高度大于最小高度的约束,因此标题不会折叠得更多。
标题中包含的内容以及如何折叠、动画完全取决于您。您可以有 2 个视图,其中底部的一个具有您的分段控制。我不会缩小这两个视图,而是让最上面的一个从屏幕上滑下来。当这种情况发生时,也许你可以减少它的 alpha 值,以便它很好地隐藏起来。
至于您的滚动视图,您需要在顶部留出一点间距。这可以通过在顶部放置空白空间来实现(表视图或集合视图意味着在顶部放置一个空/不可见的单元格、标题或部分)。或者另一种方法是使用内容插入,这也是滚动视图的属性。
当您在问题中未指定可折叠标题时,还有其他典型方面。其中之一是,如果用户在标题半折叠时停止滚动,那么您应该将其设置为完全折叠或完全展开的动画。为此,您需要使用另外 2 个委托方法:
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if decelerate == false {
snapHeader()
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
snapHeader()
}
基本上,当用户停止滚动时,滚动视图可能会立即停止,或者它会继续滚动一会儿然后停止。可以方便地使用这两种方法来检测滚动视图何时确实停止,并且您可以在该点捕捉标题。然后,标头的捕捉应该是这样的(同样可能会因您实现代码的方式而异)。
private func snapHeader() {
guard let headerMaximumHeightConstraint = headerMaximumHeightConstraint, let scrollView = self.tableView else { return }
if headerMaximumHeightConstraint.constant > collapsableHeaderMaximumHeight*0.5 {
scrollView.setContentOffset(.init(x: 0.0, y: collapsableHeaderMaximumHeight), animated: true)
} else {
scrollView.setContentOffset(.init(x: 0.0, y: collapsableHeaderMinimumHeight), animated: true)
}
}
仅应更正滚动视图内容偏移。委托方法应该能够应用其余的方法。
我希望这足以让您走上正轨。如果您发现自己陷入了一些更具体的问题,请提出更具体的问题。