2016-11-16 3 views
0

Я пытаюсь преобразовать следующий FLowLayout в Swift 3 из Objective C. К сожалению, я получаю нулевую ошибку. Кто-нибудь уже реализовал аналогичный или преобразовал этот код в Swift 3? Springy Collection View LibraryПреобразование SpringyCollectionView в Swift

Вот что я получил до сих пор:

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) 
    } 
} 

я получаю первую ошибку здесь:

enter image description here

ответ

0

Было бы лучше использовать собственные быстрые типы. Что-то вроде:

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) 
     } 
    } 

NSArray Использование и NSPredicate не статически типизированных и склонны к ошибкам времени выполнения и все вокруг не очень Swifty.

Весенний эффект работает для меня.

enter image description here

Вы можете увидеть весь код here. Возможно, это более тонкие, чем вы ожидаете.

+0

Хорошо, у меня больше нет ошибок. Но внутри моего Collectionview анимация не имеет места, кажется, как нормальный макет потока. –

+0

Это работает для меня. Я обновил свой ответ со ссылкой на весь код, который я использовал. – beyowulf

+0

Большое спасибо. Скопировал ваш код, и теперь он работает как шарм! –

Смежные вопросы