当用户向上滚动时,如何使我的 tableHeaderView 捕捉并取消捕捉到隐藏/未隐藏位置

Posted

技术标签:

【中文标题】当用户向上滚动时,如何使我的 tableHeaderView 捕捉并取消捕捉到隐藏/未隐藏位置【英文标题】:how can I make my tableHeaderView snap and unsnap to hidden/unhidden position when user scrolls up 【发布时间】:2018-05-22 12:29:59 【问题描述】:

我有一个 tableView.tableHeaderView,它是一个 UITableViewHeaderFooterView。

我希望在 tableViewController 首次出现时最初不显示此标题。当用户从 tableView 的顶部向下滚动时,我想呈现标题。

然后当用户稍微向下滚动时,我希望标题捕捉到隐藏位置。这些行为与列出所有聊天记录的 WhatsApp 页面的存档聊天标题完全相同。

有没有什么方法可以在没有一组复杂的滚动视图委托调用的情况下实现这一点?

我认为在以前版本的 swift/xcode 中,tableView.tableHeaderView 有点上下颠簸,但我注意到它不再那样做了。

我认为唯一的解决方案可能是覆盖 scrollViewDidScroll。这就是我所做的,但是当 tableView.headerView 重新出现时,它会在 tableView 的第一个单元格上这样做。不知道如何让它出现在正确的位置。

override func scrollViewDidScroll(_ scrollView: UIScrollView) 
    if let myHeaderView = self.tableView.tableHeaderView as? MyTableViewHeaderFooterView 
        let height = (self.navigationController?.navigationBar.frame.size.height)! + UIApplication.shared.statusBarFrame.size.height + self.searchController.searchBar.frame.size.height
        if scrollView.contentOffset.y < -height 
            UIView.animate(withDuration: 0.1) 
                myHeaderView.frame.size.height = 44
            
        
    

【问题讨论】:

我认为您需要阅读此答案https://***.com/a/1086288/3485139 此链接最初用于隐藏而不是捕捉。对于使用 largeTitles 的导航栏来说,它也不能顺利工作,因为在滚动之前推送和弹出到另一个 viewController 时不会考虑您改变的偏移量。这会导致一些不受欢迎的动画。寻找解决方案的方法很简单。 【参考方案1】:

这是我已经确定的,似乎在所有情况下都很好用:

var minimumTableViewInset = CGFloat(88) // this can be adjusted to 32 when the tableView is in landscape.  need observer for rotation to set that.

override func viewDidLoad() 
    super.viewDidLoad()

    tableView.register(UINib(nibName: "MyTableViewHeaderFooterView", bundle: nil), forHeaderFooterViewReuseIdentifier: "MyTableViewHeaderFooterView")

    let listsHeader = tableView.dequeueReusableHeaderFooterView(withIdentifier: "MyTableViewHeaderFooterView") as! MyTableViewHeaderFooterView

    listsHeader.alpha = 0
    listsHeader.frame.size.height = 0
    self.tableView.tableHeaderView = listsHeader


override func scrollViewDidScroll(_ scrollView: UIScrollView) 
    if let headerView = self.tableView.tableHeaderView as? MyTableViewHeaderFooterView 
        let height = (self.navigationController?.navigationBar.frame.size.height)! + UIApplication.shared.statusBarFrame.size.height + self.searchController.searchBar.frame.size.height
        if scrollView.contentOffset.y < -height 
            if headerView.frame.size.height != 44 
                tableView.beginUpdates()
                headerView.frame.size.height = 44
                tableView.endUpdates()
                UIView.animate(withDuration: 0.5) 
                    self.tableView.tableHeaderView?.alpha = 1
                
            
        
    


override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) 
    if let headerView = self.tableView.tableHeaderView as? MyTableViewHeaderFooterView 
        if scrollView.contentOffset.y > -(minimumTableViewInset - CGFloat(10)) 
            if headerView.frame.size.height != 0 
                tableView.beginUpdates()
                headerView.frame.size.height = 0
                tableView.endUpdates()
                UIView.animate(withDuration: 0.2) 
                    self.tableView.tableHeaderView?.alpha = 0
                
                tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.bottom, animated: true)
            
        
    



override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) 
    if let headerView = self.tableView.tableHeaderView as? MyTableViewHeaderFooterView 
        if scrollView.contentOffset.y > -(minimumTableViewInset - CGFloat(10)) 
            if headerView.frame.size.height != 0 
                tableView.beginUpdates()
                headerView.frame.size.height = 0
                tableView.endUpdates()
                UIView.animate(withDuration: 0.2) 
                    self.tableView.tableHeaderView?.alpha = 0
                
                tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.bottom, animated: true)
            
        
    

【讨论】:

确保自动调整大小是灵活的宽度和固定的高度,否则你会遇到各种标题问题。可以通过单击打开宽度箭头和关闭高度箭头在情节提要中轻松设置,

以上是关于当用户向上滚动时,如何使我的 tableHeaderView 捕捉并取消捕捉到隐藏/未隐藏位置的主要内容,如果未能解决你的问题,请参考以下文章

当用户向下滚动后向上滚动时,如何在表格视图中显示搜索框?

向上滚动和向下滚动时导航按钮的颜色变化

如何使我的 RelativeLayout 可滚动? [复制]

如何在向上滚动时清除 RecyclerView 中的列表

当用户向下滚动时,材质浮动操作按钮应该不可见,向上滚动时应该可见

如何在颤动中使我的文本与 listview.builder 一起滚动