Как сделать так, чтобы мои горизонтальные ячейки UICollectionView работали безупречно с разбивкой на страницы (ячейки должны быть центрированы при смахивании)? - PullRequest
0 голосов
/ 27 мая 2020

У меня есть UICollectionView в моем приложении, и я хочу, чтобы он работал так же, как представление верхней части вкладки AppStore Apps, в котором прокрутка каждой ячейки делает следующую ячейку центрированной. Я каким-то образом добился этого в своем приложении без использования свойства с включенным разбиением на страницы CollectionView, выполнил некоторые вычисления размеров и получил довольно хороший результат, но иногда он отстает. Будет очень полезно, если кто-то предложит лучший подход для достижения поведения типа магазина приложений с помощью UICollectionView :).

Пример магазина приложений. Посмотрите, как работает top collectionView. enter image description here

Где бы я ни находил этот тип реализации, везде он был реализован с помощью UIScrollView. Но я ищу точно такое же поведение с UICollectionView.

То, чего я достиг в своем приложении. enter image description here

enter image description here

Посмотреть коллекцию Посмотреть внизу. Я реализовал это поведение, переопределив метод scrollViewWillEndDragging по умолчанию для scrollView, от которого наследуется UICollectionView, и в этом методе я выполнил следующие вычисления.

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    // Stop scrollView sliding:
    targetContentOffset.pointee = scrollView.contentOffset

    let indexOfMajorCell = self.indexOfMajorCell()

    // calculate conditions:
    let dataSourceCount = collectionView(cardsCollectionView, numberOfItemsInSection: 0)
    let swipeVelocityThreshold: CGFloat = 5.0 // after some trail and error
    let hasEnoughVelocityToSlideToTheNextCell = indexOfCellBeforeDragging + 1 < dataSourceCount && velocity.x > swipeVelocityThreshold
    let hasEnoughVelocityToSlideToThePreviousCell = indexOfCellBeforeDragging - 1 >= 0 && velocity.x < -swipeVelocityThreshold
    let majorCellIsTheCellBeforeDragging = indexOfMajorCell == indexOfCellBeforeDragging
    let didUseSwipeToSkipCell = majorCellIsTheCellBeforeDragging && (hasEnoughVelocityToSlideToTheNextCell || hasEnoughVelocityToSlideToThePreviousCell)

    if didUseSwipeToSkipCell {

        let snapToIndex = indexOfCellBeforeDragging + (hasEnoughVelocityToSlideToTheNextCell ? 1 : -1)
        let toValue = collectionViewFlowLayout.itemSize.width * CGFloat(snapToIndex)

        UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: velocity.x, options: .allowUserInteraction, animations: {
            scrollView.contentOffset = CGPoint(x: toValue, y: 0)
            scrollView.layoutIfNeeded()
        }, completion: nil)

    } else {
        // This is a much better way to scroll to a cell:
        let indexPath = IndexPath(row: indexOfMajorCell, section: 0)
        cardsCollectionView.collectionViewLayout.collectionView!.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
    }
}

Примечание: Свойство включения разбиения по страницам UICollectionView было установлено в значение false в моей реализации, чтобы это работало. Когда я включаю это свойство в положение ВКЛ, показывалось странное поведение, когда часть каждой ячейки скрывалась всякий раз, когда я проводил пальцем по экрану.

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