集合视图中的UIKit Dynamics总是混乱不堪

时间:2019-05-09 14:23:08

标签: ios uikit-dynamics

当使用我的“弹性流布局”滚动(旨在复制“消息”中的滚动效果)时,初始滚动效果很好,但是重复滚动结束,所有单元格不断在整个屏幕上跳动,并偏离垂直轴

我不明白为什么单元格会偏离垂直轴,因为水平轴上没有移动。我只是将此流程布局应用于我的集合视图,该视图当前仅用于创建一堆虚拟单元格。

如何防止水平轴移动以及如何确保细胞最终始终处于静止状态

class SpringyColumnLayout: UICollectionViewFlowLayout {
    private lazy var dynamicAnimator = UIDynamicAnimator(collectionViewLayout: self)

    override func prepare() {
        super.prepare()

        guard let cv = collectionView else { return }

        let availableWidth = cv.bounds.inset(by: cv.layoutMargins).width

        let minColumnWidth: CGFloat = 300
        let maxNumberOfColumns = Int(availableWidth / minColumnWidth)
        let cellWidth = (availableWidth / CGFloat(maxNumberOfColumns))
            .rounded(.down)

        self.itemSize = CGSize(width: cellWidth, height: 70)

        self.sectionInset = UIEdgeInsets(
            top: minimumInteritemSpacing,
            left: 0,
            bottom: 0,
            right: 0
        )

        self.sectionInsetReference = .fromSafeArea

        if dynamicAnimator.behaviors.isEmpty {
            let contentSize = collectionViewContentSize
            let contentBounds = CGRect(origin: .zero, size: contentSize)
            guard let items = super.layoutAttributesForElements(in: contentBounds)
                else { return }

            for item in items {
                let spring = UIAttachmentBehavior(
                    item: item,
                    attachedToAnchor: item.center
                )
                spring.length = 0
                spring.damping = 0.8
                spring.frequency = 1

                self.dynamicAnimator.addBehavior(spring)
            }
        }
    }

    override func layoutAttributesForElements(
        in rect: CGRect
    ) -> [UICollectionViewLayoutAttributes]? {
        return dynamicAnimator.items(in: rect) as? [UICollectionViewLayoutAttributes]
    }

    override func layoutAttributesForItem(
        at indexPath: IndexPath
    ) -> UICollectionViewLayoutAttributes? {
        return dynamicAnimator.layoutAttributesForCell(at: indexPath)
    }

    override func shouldInvalidateLayout(
        forBoundsChange newBounds: CGRect
    ) -> Bool {
        let scrollView = self.collectionView!

        let scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y
        let touchLocation = scrollView.panGestureRecognizer
            .location(in: scrollView)

        for case let spring as UIAttachmentBehavior in dynamicAnimator.behaviors {
            let anchorPoint = spring.anchorPoint
            let yDistanceFromTouch = abs(touchLocation.y - anchorPoint.y)
            let xDistanceFromTouch = abs(touchLocation.x - anchorPoint.x)
            let scrollResistance = (yDistanceFromTouch + xDistanceFromTouch) / 1500

            let item = spring.items.first!
            var center = item.center
            if scrollDelta < 0 {
                center.y += max(scrollDelta, scrollDelta * scrollResistance)
            } else {
                center.y += min(scrollDelta, scrollDelta * scrollResistance)
            }
            item.center = center

            dynamicAnimator.updateItem(usingCurrentState: item)
        }

        return false
    }
}

0 个答案:

没有答案