【问题标题】:CollectionView scroll to newly inserted itemCollectionView 滚动到新插入的项目
【发布时间】:2019-03-11 15:02:26
【问题描述】:

我有一个由 NSFetchedResultsController 驱动的 CollectionView。

CollectionViewLayout 是按名称升序排列的水平“轮播”单元格布局。

插入带有海关动画的新物品。

 func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

if type == NSFetchedResultsChangeType.Insert {
    println("Insert Object: \(newIndexPath)")

   UIView.animate(withDuration: 1.0, delay: 0.0, options: .curveEaseOut, animations: {
       self.collectionView?.insertItems(at: [newIndexPath])
   }, completion: { finished in
       self.collectionView?.scrollToItem(at: newIndexPath, at: .centeredHorizontally, animated: true)
})
    )
...

它可以工作,但动画有点小故障,并且滚动同时发生。

我想滚动到 Item 然后用自定义动画插入它,但如果我在插入之前滚动到 Item 应用程序崩溃。

在这里做什么是正确的?

谢谢

【问题讨论】:

    标签: swift animation uicollectionview nsfetchedresultscontroller


    【解决方案1】:

    我会尝试的第一件事是将animate(withDuration:delay:options:animations:completion:) 替换为performBatchUpdates(_:completion:)

    func controller(controller: NSFetchedResultsController,
                    didChangeObject anObject: AnyObject,
                    atIndexPath indexPath: NSIndexPath?,
                    forChangeType type: NSFetchedResultsChangeType,
                    newIndexPath: NSIndexPath?)
    {
    
        if type == NSFetchedResultsChangeType.Insert {
            println("Insert Object: \(newIndexPath)")
    
        self.collectionView?.performBatchUpdates({
            self.collectionView?.insertItems(at: [newIndexPath])
        }, completion: { finished in
            self.collectionView?.scrollToItem(at: newIndexPath, at: .centeredHorizontally, animated: true)
        })
        …
    }
    

    如果这仍然给您带来问题,那么您可以在下一个运行循环中调用滚动。

    func controller(controller: NSFetchedResultsController,
                    didChangeObject anObject: AnyObject,
                    atIndexPath indexPath: NSIndexPath?,
                    forChangeType type: NSFetchedResultsChangeType,
                    newIndexPath: NSIndexPath?)
    {
    
        if type == NSFetchedResultsChangeType.Insert {
            println("Insert Object: \(newIndexPath)")
    
        self.collectionView?.performBatchUpdates({
            self.collectionView?.insertItems(at: [newIndexPath])
        }, completion: { finished in
            DispatchQueue.main.async { // Defer to next runlop.
                self.collectionView?.scrollToItem(at: newIndexPath, at: .centeredHorizontally, animated: true)
            }
        })
        …
    }
    

    最后,您可以尝试只为滚动部分设置动画。

    func controller(controller: NSFetchedResultsController,
                    didChangeObject anObject: AnyObject,
                    atIndexPath indexPath: NSIndexPath?,
                    forChangeType type: NSFetchedResultsChangeType,
                    newIndexPath: NSIndexPath?)
    {
    
        if type == NSFetchedResultsChangeType.Insert {
            println("Insert Object: \(newIndexPath)")
    
        self.collectionView?.reloadItems(at: [newIndexPath]) // reload without animating.
    
        DispatchQueue.main.async { // Defer to next runlop.
            self.collectionView?.scrollToItem(at: newIndexPath, at: .centeredHorizontally, animated: true)
        }
        …
    }
    

    【讨论】:

      【解决方案2】:

      通过查看函数,我可以想象您看到的故障是 CollectionView 向前滚动然后橡皮筋/“传送”回来。

      我认为这可能是因为您试图同时运行两个动画。 你的第一个动画,UIView.animate(),动画滚动到新插入的项目;但是,当您调用 collectionView?.scrollToItem() 时,您也会对其进行动画处理(见下文)

      self.collectionView?.scrollToItem(..., animated: true) <--
      

      这可能是它不起作用的原因;您正在尝试制作动画。 尝试将动画设置为 false,看看是否可以解决问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-22
        • 2017-10-02
        • 1970-01-01
        • 2017-12-21
        • 2017-01-17
        • 1970-01-01
        相关资源
        最近更新 更多