CollectionView с пользовательским макетом потока не вызывает didSelectItemAt - PullRequest
0 голосов
/ 04 ноября 2019

Я создал viewController, который содержит GSMMap и collectionView (по горизонтали), как карта Google. Я использовал приведенный ниже код для центрирования и привязки элементов.

class ZoomAndSnapFlow: UICollectionViewFlowLayout {

let activeDistance: CGFloat = 200
let zoomFactor: CGFloat = 0.3

override init() {
    super.init()

    scrollDirection = .horizontal
    minimumLineSpacing = 40
    itemSize = CGSize(width: 200, height: 157)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func prepare() {
    guard let collectionView = collectionView else { fatalError() }
    let verticalInsets = (collectionView.frame.height - collectionView.adjustedContentInset.top - collectionView.adjustedContentInset.bottom - itemSize.height) / 2
    let horizontalInsets = (collectionView.frame.width - collectionView.adjustedContentInset.right - collectionView.adjustedContentInset.left - itemSize.width) / 2
    sectionInset = UIEdgeInsets(top: verticalInsets, left: horizontalInsets, bottom: verticalInsets, right: horizontalInsets)

    super.prepare()
}

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    guard let collectionView = collectionView else { return nil }
    let rectAttributes = super.layoutAttributesForElements(in: rect)!.map { $0.copy() as! UICollectionViewLayoutAttributes }
    let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.frame.size)

    // Make the cells be zoomed when they reach the center of the screen
    for attributes in rectAttributes where attributes.frame.intersects(visibleRect) {
        let distance = visibleRect.midX - attributes.center.x
        let normalizedDistance = distance / activeDistance

        if distance.magnitude < activeDistance {
            let zoom = 1 + zoomFactor * (1 - normalizedDistance.magnitude)
            attributes.transform3D = CATransform3DMakeScale(zoom, zoom, 1)
            attributes.zIndex = Int(zoom.rounded())
        }
    }

    return rectAttributes
}

override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
    guard let collectionView = collectionView else { return .zero }

    // Add some snapping behaviour so that the zoomed cell is always centered
    let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionView.frame.width, height: collectionView.frame.height)
    guard let rectAttributes = super.layoutAttributesForElements(in: targetRect) else { return .zero }

    var offsetAdjustment = CGFloat.greatestFiniteMagnitude
    let horizontalCenter = proposedContentOffset.x + collectionView.frame.width / 2

    for layoutAttributes in rectAttributes {
        let itemHorizontalCenter = layoutAttributes.center.x
        if (itemHorizontalCenter - horizontalCenter).magnitude < offsetAdjustment.magnitude {
            offsetAdjustment = itemHorizontalCenter - horizontalCenter
        }
    }

    return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
}

override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
    // Invalidate layout so that every cell get a chance to be zoomed when it reaches the center of the screen
    return true
}

override func invalidationContext(forBoundsChange newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext {
    let context = super.invalidationContext(forBoundsChange: newBounds) as! UICollectionViewFlowLayoutInvalidationContext
    context.invalidateFlowLayoutDelegateMetrics = newBounds.size != collectionView?.bounds.size
    return context
}

}

У меня две проблемы:

  1. в методе scrollViewDidEndDecelerating Я хочу определить, какой элементвыбран для изменения камеры карты, но когда я использую collectionView.indexPathForItem(at: collectionView.center), он возвращает ноль, я проверил координату. это был центр предмета

  2. didSelectItemAt вообще не срабатывает. делегат установлен (прокрутить делегат работает)

1 Ответ

1 голос
/ 04 ноября 2019

Первый вопрос:

let centerX = collectionView.contentOffset.x + collectionView.frame.width * 0.5
let centerY = collectionView.contentOffset.y + collectionView.frame.height * 0.5
collectionView.indexPathForItem(at: CGPoint(x: centerX, y: centerY))

Второй:

didSelectItemAt() только что сработал, когда gestureRecognizer событие, поэтому вы должны вызывать все, что хотите вручную. Надеюсь, это поможет вам.

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