UICollectionViewController с динамическим заголовком (как приложение Reddit) - PullRequest
0 голосов
/ 30 мая 2019

Я ищу способ реализовать представление заголовка, которое автоматически скрывается, как только вы начинаете прокручивать вниз, и сразу же показывает себя, как только пользователь начинает прокручивать вверх. Обычно я всегда публикую некоторый код, но сейчас я немного растерялся, как реализовать такое поведение.

Мой макет просмотра:

  • UICollectionViewController с включенной подкачкой для горизонтального прокрутка (имеет две позиции)
  • UICollectionViewCell заполняет все вертикальное пространство. Каждый UICollectionViewCell содержит UITableView для вертикальной прокрутки. Я предполагаю, что мне нужно использовать вертикальную позицию прокрутки UITableView для настройки рамки строки меню.

Видео: https://imgur.com/a/Rdu3wko

Как лучше всего реализовать такое поведение?

Ответы [ 2 ]

1 голос
/ 08 июня 2019

Если вы хотите использовать 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
    }
0 голосов
/ 30 мая 2019

Эта функция возможна в UITableView установить заголовок параллакса, в противном случае UIScrollView анимация параллакса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...