重新排序 CollectionView 单元格 iOS 11

Posted

技术标签:

【中文标题】重新排序 CollectionView 单元格 iOS 11【英文标题】:Reordering CollectionView cells iOS 11 【发布时间】:2017-09-02 20:36:38 【问题描述】:

我知道 ios 11 为 collectionview 带来了新的拖放功能,但我在使用它时遇到了一个完全不同的问题。所以我想我会尝试使用 IOS 9 (see this link) 中引入的旧方法。我的问题是,在 iOS 11 上,仅当切换两个单元格时,移除手指时的结束动画才会奇怪。你可以在这个clip看到问题。

几天来我一直在尝试解决这个问题,但没有运气。它在 iOS 10 上运行良好,但在 iOS 11 上运行良好。任何帮助将不胜感激。

额外信息:我正在使用带有长按手势的集合视图来启动重新排序手势,如第一个链接中所示。但是,在使用 uicollectionviewcontroller 时仍然会出现问题

这是长按手势的代码:

func handleLongGesture(gesture: UILongPressGestureRecognizer) 

    switch(gesture.state) 

    case .began:
        guard let selectedIndexPath = self.collectionView.indexPathForItem(at: gesture.location(in: self.collectionView)) else 
            break
        
        collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
    case .changed:
        collectionView.updateInteractiveMovementTargetPosition(gesture.location(in: gesture.view!))
    case .ended:
      // this part misbehaves on ios 11 when two cells are swapped
        collectionView.performBatchUpdates(
            self.collectionView.endInteractiveMovement()
        )
    default:
        collectionView.cancelInteractiveMovement()
    

【问题讨论】:

请添加一些代码sn-ps来说明你的问题,让帮助你更容易。 我在水平的collectionview中遇到了完全相同的问题,但不是垂直的。你的是水平的吗? 这很奇怪……我的是垂直的 你解决过这个问题吗?我遇到了完全相同的问题。 更新:我在调用 endInteractiveMovement() 后无意中调用了 invalidateLayout()。 invalidateLayout() 给我造成了丑陋的动画故障。不调用 invalidateLayout() 似乎已经为我修复了它。 【参考方案1】:

首先,您无需将collectionView.endInteractiveMovement() 放在performBatchUpdates 块内。但尽管如此,这个问题也让我很烦恼。 iOS 10 和 11 与 endInteractiveMovement 之间的差异没有多大意义。

对于我的问题,我在我的 collectionView 上方放置了一个假快照单元格,并在我运行手势状态更改和 updateInteractiveMovementTargetPosition 时隐藏了下面的内容。一旦手势状态为.ended,我正在从超级视图中删除假单元格,然后执行endInteractiveMovement。但是现在使用 iOS 11,我在上一个答案的 cmets 中遇到了与 @prolfe 相同的问题。由于有问题的单元的这种无法预料的重新加载,我得到了这个奇怪的闪光。

我最终采用的解决方案是延迟我的假细胞移除,这样它就可以“掩盖”闪光。

我的pushBackView 方法将假单元格动画化回放置位置,然后删除假单元格。然后我制定延迟:

case .ended:

        fakeCellView?.pushBackView  [weak self] in // 'suppress' cell animation

            DispatchQueue.main.asyncAfter(deadline: .seconds(0.01), execute: 
                self?.fakeCellView?.removeFromSuperview()
            )

            self?.collectionView?.endInteractiveMovement()
        

希望这会有所帮助!

【讨论】:

所以您指望移动单元的重新加载会在 1/100 秒内发生,对吧?我觉得这不是一个保证的事情。聪明,但不是一个很好的解决方案。我仍在寻找可以在调用endInteractiveMovement() 之后最终确定项目失效和单元格重新加载完成的内容。【参考方案2】:

无需在 performBatchUpdates 块内执行self.collectionView.endInteractiveMovement()

【讨论】:

iOS 10 有必要避免在拖动过程中松开单元格的奇怪行为。我希望它在 iOS 11 中的功能类似,但事实并非如此。 iOS10我没试过,我正在做一个新的iOS11项目。如果它在两个操作系统中的行为不同,为什么不使用:if #available(iOS 11.0, *) /* iOS11 code */ else /* iOS10 code */ 。我知道这很烦人,但 collectionViews 发生了一些变化.. 是的,我也尝试过,最糟糕的是,无论是否调用 performBatchUpdates,iOS 11 的行为都出乎意料。自 iOS 11 正式发布以来,我一直无法检查它是否已得到纠正。 我也遇到了 iOS 11 和 endIntractiveMovement 功能的问题。似乎 CollectionView 正在重新加载移动后很快移动的单元格(异步)。所以对我来说,我看到了闪光。而且由于该单元格的延迟重新加载,此后我也无法进行任何其他collectionview操作。 #available 在这里并不真正适用,因为我发现 iOS 11 中没有一个好的替代方案。 ?

以上是关于重新排序 CollectionView 单元格 iOS 11的主要内容,如果未能解决你的问题,请参考以下文章

可重新排序的自定义 collectionview 布局

UICollectionView 单元格重新排序

重新排序 UICollectionView 的单元格

如何在锁定其中一些单元格时重新排序 UICollectionView 单元格

保存重新排序的uicollectionview单元格无法正常工作

使用自定义维度重新排序集合视图单元格时出现问题