UICollectionViewController с динамическим заголовком (например, приложение Reddit)

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

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

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

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

Что было бы лучшим способом реализовать такое поведение?

Я думаю, что это UITableview, а не представление коллекции

Yogesh Patel 30.05.2019 13:41

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

inexcitus 06.06.2019 05:38

Может быть, это поможет вам github.com/cillyfly/MXScroll

Nikunj Kumbhani 08.06.2019 09:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
368
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Здравствуйте, у вас есть пример? Может быть, вы пришлете мне ссылку?

inexcitus 06.06.2019 05:37

Проверьте это [medium.com/if-let-swift-programming/… [github.com/romansorochak/ParallaxHeader] [github.com/maxep/MXParallaxHeader]] Вы можете ссылаться на [cococontrols.com/search?q=parallax] также вы ищете на [cocopods.org] и многие другие .

Mitesh Mewada 06.06.2019 07:26

Я думаю, что это намного усложняет тот факт, что у меня есть UICollectionView с горизонтальной прокруткой. В ваших примерах используется только один UITableView.

inexcitus 06.06.2019 07:29

Если вы хотите использовать UICollectionView набор UIScrollView для установки параллаксной анимации.

Mitesh Mewada 06.06.2019 07:42

@J.Doe все ссылки работают отлично, когда вы открываете ссылку, проверьте, что ULRLink открыт с ], поэтому, пожалуйста, удалите, это сработало, и теперь я не могу редактировать свой ответ, поэтому я не мог обновить свой ответ.

Mitesh Mewada 08.06.2019 07:43
Ответ принят как подходящий

Если вы хотите использовать 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
    }

Спасибо, я постараюсь внедрить это решение в свое приложение.

inexcitus 08.06.2019 21:05

Без проблем! Добавлена ​​​​альтернатива выше, если вам это нужно.

jake 08.06.2019 21:08

Привет, у меня есть еще один вопрос: теперь заголовок отображается и прокручивается очень плавно, это выглядит очень красиво, еще раз спасибо. Однако представление покрывает первую ячейку. Как я могу изменить поведение, чтобы ячейка начиналась прямо под меню заголовка? Я видел свойство contentInset, но программное изменение contentInset сделало UIScrollView «дерганым». Есть ли лучшее решение?

inexcitus 11.06.2019 05:32

Замените строку header.bottomAnchor.constraint(equalTo: self.view.topAnchor).isActive = true на header.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true. Затем удалите эту строку: collectionView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true и добавьте ее после того, как вы добавите заголовок в качестве подпредставления: `collectionView.topAnchor.constraint(equalTo: header.bottomAnchor).isActive = true

jake 11.06.2019 06:06

Поскольку я больше не использую UIViewConroller (а вместо этого использую UICollectionViewController), мне пришлось немного подправить некоторые вещи, но ваш код мне очень помог, так что большое вам спасибо, теперь он наконец работает и выглядит очень хорошо.

inexcitus 13.06.2019 08:44

Другие вопросы по теме