具有动态标头的UICollectionViewController

时间:2019-05-30 11:36:47

标签: ios swift uicollectionview

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

我的视图布局: * UICollectionViewController,启用了用于水平滚动的分页。 *我有两个项目,每个项目都有一个UICollectionViewCell,可托管另一个UIScrollView进行垂直滚动。

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

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

2 个答案:

答案 0 :(得分:1)

如果要使用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
    }

答案 1 :(得分:0)

UITableView设置视差标头中可以使用此功能,否则可以在UIScrollView视差动画中使用。

相关问题