【问题标题】:Converting SpringyCollectionView to Swift将 SpringyCollectionView 转换为 Swift
【发布时间】:2016-11-16 21:17:13
【问题描述】:

我正在尝试将以下 FLowLayout 从 Objective C 转换为 Swift 3。不幸的是,我收到了一个 null 错误。有人已经实现了类似的代码或将此代码转换为 Swift 3 吗? Springy Collection View Library

这是我目前得到的:

override func prepare() {
    super.prepare()


    // Need to overflow our actual visible rect slightly to avoid flickering.
    let visibleRect = self.collectionView!.bounds.insetBy(dx: -100, dy: -100)
    let itemsInVisibleRectArray: NSArray = super.layoutAttributesForElements(in: visibleRect)! as NSArray
    let itemsIndexPathsInVisibleRectSet: NSSet = NSSet(array: itemsInVisibleRectArray.value(forKey: "indexPath") as! [AnyObject])

    // Step 1: Remove any behaviours that are no longer visible.
    let noLongerVisibleBehaviours = (self.dynamicAnimator.behaviors as NSArray).filtered(using: NSPredicate(block: {behaviour, bindings in
        let currentlyVisible: Bool = itemsIndexPathsInVisibleRectSet.member((behaviour as! UIAttachmentBehavior).items.first!) != nil
        return !currentlyVisible
    }))


    for (_, obj) in noLongerVisibleBehaviours.enumerated() {
        self.dynamicAnimator.removeBehavior(obj as! UIDynamicBehavior)
        self.visibleIndexPathsSet.remove((obj as! UIAttachmentBehavior).items.first!)
    }

    // Step 2: Add any newly visible behaviours.
    // A "newly visible" item is one that is in the itemsInVisibleRect(Set|Array) but not in the visibleIndexPathsSet
    let newlyVisibleItems = itemsInVisibleRectArray.filtered(using: NSPredicate(block: {item, bindings in
        let currentlyVisible: Bool = self.visibleIndexPathsSet.member(item!) != nil
        return !currentlyVisible
    }))

    let touchLocation: CGPoint = self.collectionView!.panGestureRecognizer.location(in: self.collectionView)

    for (_, item) in newlyVisibleItems.enumerated() {
        let springBehaviour: UIAttachmentBehavior = UIAttachmentBehavior(item: item as! UIDynamicItem, attachedToAnchor: (item as AnyObject).center)

        springBehaviour.length = CGFloat(kLength)
        springBehaviour.damping = CGFloat(kDamping)
        springBehaviour.frequency = CGFloat(kFrequence)

        let zeropoint = CGPoint(x: 0,y :0)

        // If our touchLocation is not (0,0), we'll need to adjust our item's center "in flight"
        if (!zeropoint.equalTo(touchLocation)) {
            let yDistanceFromTouch = fabsf(Float(touchLocation.y - springBehaviour.anchorPoint.y))
            let xDistanceFromTouch = fabsf(Float(touchLocation.x - springBehaviour.anchorPoint.x))
            let scrollResistance = (yDistanceFromTouch + xDistanceFromTouch) / Float(kResistence)

            let item = springBehaviour.items.first as! UICollectionViewLayoutAttributes
            var center = item.center

            if self.latestDelta < 0 {
                center.x += max(self.latestDelta, self.latestDelta * CGFloat(scrollResistance))
            } else {
                center.x += min(self.latestDelta, self.latestDelta * CGFloat(scrollResistance))
            }

            item.center = center
        }

        self.dynamicAnimator.addBehavior(springBehaviour)
        self.visibleIndexPathsSet.add(item)
    }
}

我在这里遇到第一个错误:

【问题讨论】:

    标签: ios uicollectionview swift3 flowlayout


    【解决方案1】:

    最好使用原生 swift 类型。比如:

        override func prepare()
        {
            super.prepare()
            let visibleRect = CGRect(origin: self.collectionView?.bounds.origin ?? CGPoint.zero, size: self.collectionView?.frame.size ?? CGSize.zero).insetBy(dx: -100, dy: -100)
    
            let itemsInVisibleRectArray = super.layoutAttributesForElements(in: visibleRect) ?? []
            let itemsIndexPathsInVisibleRectSet = Set(itemsInVisibleRectArray.map{ $0.indexPath })
    
            let noLongerVisibleBehaviors = self.dynamicAnimator.behaviors.filter
            { behavior in
                guard let behavior = behavior as? UIAttachmentBehavior else { return false }
                guard let attribute = behavior.items.first as? UICollectionViewLayoutAttributes else { return false }
                let currentlyVisible = itemsIndexPathsInVisibleRectSet.contains(attribute.indexPath)
                return !currentlyVisible
            }
    
            noLongerVisibleBehaviors.forEach
            { behavior in
                self.dynamicAnimator.removeBehavior(behavior)
                guard let behavior = behavior as? UIAttachmentBehavior else { return }
                guard let attribute = behavior.items.first as? UICollectionViewLayoutAttributes else { return }
                self.visibleIndexPathsSet.remove(attribute.indexPath)
            }
    
            let newlyVisibleItems = itemsInVisibleRectArray.filter
            { item in
                let currentlyVisible = self.visibleIndexPathsSet.contains(item.indexPath)
                return !currentlyVisible
            }
            let touchLocation = self.collectionView?.panGestureRecognizer.location(in: self.collectionView)
    
            newlyVisibleItems.forEach
            { item in
                var center = item.center
                let springBehavior = UIAttachmentBehavior(item: item, attachedToAnchor: center)
    
                springBehavior.length = 0.0
                springBehavior.damping = 0.8
                springBehavior.frequency = 1.0
    
                if CGPoint.zero != touchLocation
                {
                    let yDistanceFromTouch = fabs(touchLocation?.y ?? 0 - springBehavior.anchorPoint.y)
                    let xDistanceFromTouch = fabs(touchLocation?.x ?? 0 - springBehavior.anchorPoint.x)
                    let scrollResistance = (yDistanceFromTouch + xDistanceFromTouch) / 1500.0
    
                    if self.latestDelta < 0.0
                    {
                        center.y += max(self.latestDelta, self.latestDelta * scrollResistance)
                    }
                    else
                    {
                        center.y += min(self.latestDelta, self.latestDelta * scrollResistance)
                    }
                    item.center = center
                }
                self.dynamicAnimator.addBehavior(springBehavior)
                self.visibleIndexPathsSet.insert(item.indexPath)
            }
        }
    

    使用NSArrayNSPredicate 不是静态类型的,容易出现运行时错误,而且不是很迅速。

    弹簧效应对我有用。

    你可以看到所有的代码here.可能比你想象的更微妙。

    【讨论】:

    • 好的,我没有任何错误了。但是在我的 Collectionview 中没有动画发生,看起来像正常的流布局。
    • 它对我有用。我用我使用的所有代码的链接更新了我的答案。
    • 非常感谢。复制了你的代码,现在它就像一个魅力!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    • 2014-10-06
    • 2017-10-10
    • 2015-10-24
    • 1970-01-01
    相关资源
    最近更新 更多