我正在寻找一种实现标题视图的方法,该视图在您开始向下滚动时将自动隐藏,并在用户开始向上滚动时立即显示其自身。
通常,我总是发布一些代码,但是现在我对如何实现这种行为有些迷茫。

我的视图布局:


UICollectionViewController启用水平分页
滚动(有两个项目)
UICollectionViewCell填充整个垂直空间。每个UICollectionViewCell都承载一个UITableView以进行垂直滚动。我假设我必须使用UITableView垂直滚动位置来调整菜单栏的框架。


视频:https://imgur.com/a/Rdu3wko

实施这种行为的最佳方法是什么?

最佳答案

如果要使用UICollectionView,只需抓住委托,查看用户滚动的方向,然后根据需要隐藏/显示标题。这是一个入门的示例:

class ViewController: UIViewController {

    // Variable to save the last scroll offset.
    private var lastContentOffset: CGFloat = 0

    private lazy var header: UIView = {
        let header = UIView()
        header.translatesAutoresizingMaskIntoConstraints = false
        header.backgroundColor = .red
        header.widthAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
        header.heightAnchor.constraint(equalToConstant: 80.0).isActive = true
        return header
    }()

    private lazy var collectionView: UICollectionView = {
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout())
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.delegate = self
        collectionView.backgroundColor = .white
        collectionView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: 2000.0)
        // Setting bounces to false - otherwise the header will disappear when we go past the top and are sprung back.
        collectionView.bounces = false
        return collectionView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(collectionView)
        collectionView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        collectionView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        collectionView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        collectionView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: 2000.0)

        // Make sure you either add the header subview last, or call self.view.bringSubviewToFront(header)
        self.view.addSubview(header)
        // Constrain the header so it's just sitting on top of the view. To make it visible, we'll use a transform.
        header.bottomAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        header.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true

        // Header starts visible.
        header.layoutIfNeeded()
        self.header.transform = CGAffineTransform(translationX: 0.0, y: header.frame.height)
    }

    func revealHeader() {
        // Set the duration below to how quickly you want header to appear/disappear.
        UIView.animate(withDuration: 0.3) {
            self.header.transform = CGAffineTransform(translationX: 0.0, y: self.header.frame.height)
        }

    }

    func hideHeader() {
        UIView.animate(withDuration: 0.3) {
            self.header.transform = .identity
        }
    }

}

extension ViewController: UICollectionViewDelegate {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if (lastContentOffset > scrollView.contentOffset.y) {
            // Scrolled up: reveal header.
            revealHeader()
        }
        else if (lastContentOffset < scrollView.contentOffset.y) {
            // Scrolled down: reveal header.
            hideHeader()
        }

        lastContentOffset = scrollView.contentOffset.y
    }

}




编辑:注意Reddit标头的功能有些不同。如果您希望事物动态滚动(即向下滚动的数量而不是一次全部滚动),请使用以下代码替换该委托函数:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if (lastContentOffset > scrollView.contentOffset.y) {
        // Scrolled up: reveal header.
        let difference = lastContentOffset - scrollView.contentOffset.y
        if header.transform.ty < (header.frame.height - difference) {
            // Header hasn't been fully revealed yet, bring it down by the amount we've scrolled up.
            self.header.transform = CGAffineTransform(translationX: 0.0, y: header.transform.ty + difference)
        } else {
                self.header.transform = CGAffineTransform(translationX: 0.0, y: header.frame.height)
        }
    }
        else if (lastContentOffset < scrollView.contentOffset.y) {
            // Scrolled down: reveal header.
            let difference = scrollView.contentOffset.y - lastContentOffset
            if header.transform.ty > difference {
                self.header.transform = CGAffineTransform(translationX: 0.0, y: header.transform.ty - difference)
            } else {
                self.header.transform = CGAffineTransform(translationX: 0.0, y: 0.0)
            }
        }

        lastContentOffset = scrollView.contentOffset.y
    }

07-28 02:15
查看更多