如何在滚动时更改 UIView 大小并延迟

Posted

技术标签:

【中文标题】如何在滚动时更改 UIView 大小并延迟【英文标题】:How can I change UIView size on scroll w/ a delay 【发布时间】:2019-05-17 09:17:54 【问题描述】:

我有一个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 
        ..........

但这并没有按预期工作。

希望能达到和大标题导航栏滚动效果一样的效果。

【问题讨论】:

【参考方案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

我相信你应该会得到想要的效果。

【讨论】:

【参考方案2】:

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

例如 如果向下滚动并显示条形并且contentOffset.y 大于 500 - 缩小它。

如果向上滚动并且栏缩小并且contentOffset.y 小于 300 - 显示它。

【讨论】:

以上是关于如何在滚动时更改 UIView 大小并延迟的主要内容,如果未能解决你的问题,请参考以下文章

如何在更改 UIView 大小时应用动画? + 斯威夫特 5

如何在启用自动布局的情况下更改 iOS6 中的 UIView 大小?

如何更改 UIView 大小?

如何将 UIView 锚定到屏幕上的特定位置并在滚动时将其保留在那里

如何在调整大小时更改 Malihu 自定义滚动条 snapAmoun?

如何在 ios 中使用自动布局更改滚动视图内容大小