如何更改带有延迟的滚动时的UIView大小

时间:2019-05-17 09:17:55

标签: swift uitableview uiview autolayout

我有一个UIView锚定到topleadingtrailing锚定。初始高度为138,并且应缩小到不小于88

我在此视图的底部有一个UITableView锚定的顶部,它也锚定在超级视图的leadingtrailing和底部。

它不是表视图的标题视图,而是一个单独的视图。

在滚动表格视图时,我希望UIView缩小并根据滚动方向重置回其初始大小。

  • 向上滚动=缩小到不小于88
  • 向下滚动=增加到不超过138

我目前能够通过使用

实现这一目标
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    onUserScroll?(scrollView)
}

通过绑定触发以下代码

class FeedView: UIView {
    private(set) var brandedHeader: UIView!
    private(set) var brandedHeaderHeight: NSLayoutConstraint!
    private(set) var tableView: UITableView!

    private lazy var maxHeaderHeight: CGFloat = 138
    private lazy var minHeaderHeight: CGFloat = 88
    private var previousScrollOffset: CGFloat = 0

    ...............

}
    extension FeedView {
        func setTableViewDelegate(_ delegate: TableViewDelegate) {
            tableView.delegate = delegate
            tableView.dataSource = delegate
        }

        func onUserScroll(_ scrollView: UIScrollView) {

            let scrollDiff = scrollView.contentOffset.y - self.previousScrollOffset

            let absoluteTop: CGFloat = 0
            let absoluteBottom: CGFloat = scrollView.contentSize.height - scrollView.frame.size.height

            let isScrollingDown = scrollDiff > 0 && scrollView.contentOffset.y > absoluteTop
            let isScrollingUp = scrollDiff < 0 && scrollView.contentOffset.y < absoluteBottom

            guard canAnimateHeader(scrollView) else { return }

            // Calculate new header height
            var newHeight = self.brandedHeaderHeight.constant
            if isScrollingDown {
                newHeight = max(self.minHeaderHeight, self.brandedHeaderHeight.constant - abs(scrollDiff))
            } else if isScrollingUp {
                newHeight = min(self.maxHeaderHeight, self.brandedHeaderHeight.constant + abs(scrollDiff))
            }

            // Header needs to animate
            if newHeight != self.brandedHeaderHeight.constant {
                self.brandedHeaderHeight.constant = newHeight
                self.setScrollPosition(self.previousScrollOffset)
            }

            self.previousScrollOffset = scrollView.contentOffset.y
        }

        private func canAnimateHeader(_ scrollView: UIScrollView) -> Bool {
            // Calculate the size of the scrollView when header is collapsed
            let scrollViewMaxHeight = scrollView.frame.height + self.brandedHeaderHeight.constant - minHeaderHeight

            // Make sure that when header is collapsed, there is still room to scroll
            return scrollView.contentSize.height > scrollViewMaxHeight
        }

        private func setScrollPosition(_ position: CGFloat) {
            self.tableView.contentOffset = CGPoint(x: self.tableView.contentOffset.x, y: position)
        }
    }

但是我想做的是延迟调整大小事件。

当前它开始立即向上或向下滚动,实际上我想让它在用户向上滚动X量后开始调整大小,然后仅在他们再次通过该点时才向下滚动调整大小。

我的代码更新如下

private var previousScrollOffset: CGFloat = 100 // offset the initial scroll so the header does not shrink immediately on scroll

然后也是

    func onUserScroll(_ scrollView: UIScrollView) {

        guard scrollView.contentOffset.y < 200 else { return }
        ..........
}

但这不能按预期工作。

我希望能达到与大标题导航栏滚动效果相同的效果。

2 个答案:

答案 0 :(得分:1)

使用

更新您的onUserScroll函数
    let isScrollingDown = scrollDiff > 0 && scrollView.contentOffset.y > absoluteTop && scrollView.contentOffset.y > 300
    let isScrollingUp = scrollDiff < 0 && scrollView.contentOffset.y < absoluteBottom && scrollView.contentOffset.y < 300

我相信您会获得理想的效果。

答案 1 :(得分:0)

使用多个y常数开始缩小/显示顶部栏。

例如 如果向下滚动并显示该条,并且contentOffset.y大于500,则将其缩小。

如果向上滚动且栏缩小并且contentOffset.y小于300,则将其显示出来。