UICollectionViewFlowLayout 中的动画更改

Animate changes in UICollectionViewFlowLayout

我正在使用 UICollectionViewFlowLayout 在水平滚动视图中排列视图图块。默认情况下,我使用 UICollectionViewDelegateFlowLayout:

将它们设为正方形
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    var nominalSize = CGSize(width: collectionView.frame.height, height: collectionView.frame.height)
    return nominalSize
}

通过这种方式,我得到了正方形的瓷砖,其大小与 collectionView 的电流大小相匹配。但是,在某些情况下,我会修改某些图块的标称尺寸,因此它会稍微演变为:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    var nominalSize = CGSize(width: collectionView.frame.height, height: collectionView.frame.height)
    if someTest(indexPath) {
        nominalSize = self.tweakNominalSize(nominalSize)
    }
    return nominalSize
}

我还没有弄清楚的是如何触发集合视图以 A) 召回委托以重新布局和 B) 如何让它为更改设置动画。

我尝试过的:

1)

self.myCollectionView.setNeedsLayout()
UIView.animateWithDuration(200.milliseconds) {
    self.myCollectionView.layoutIfNeeded()
}

这没有任何作用。 print() 委托回调中的语句显示它从未被调用。

2)

self.schedulesView.setCollectionViewLayout(
    self.schedulesView.collectionViewLayout,
    animated: true)

这也没有任何作用。我不确定它是聪明还是什么。也许它足够聪明,注意到它们是相同的并选择退出?

3)

self.schedulesView.startInteractiveTransition(
    to: self.schedulesView.collectionViewLayout,
    completion: nil)
self.schedulesView.finishInteractiveTransition()

这确实会导致布局发生!但一点也不生动。它只是突然改变。它似乎将图块的右侧保持在原来的位置,而不是左侧,并且它似乎在我在两次调用之间进行的其他 UI 更改之后明显发生。

你的 collectionView(_:layout:sizeForItemAt:) 在我看来是正确的(我有类似的东西)。

您需要调用 performBatchUpdates(_:completion:) AFTER you make your changes and BEFORE you calllayoutIfNeeded`。

// Some call that makes your call to `someTest()` in `collectionView(_:layout:sizeForItemAt:)` return what you want
myCollectionView.performBatchUpdates(nil, completion: nil)
myCollectionView.layoutIfNeeded()

不需要调用 myCollectionView.setNeedsLayout(),因为 performBatchUpdates(_,completion) 会为您设置。

特别是,我所做的是:

self.myCollectionView.performBatchUpdates({ 
    self.causeSomeOtherVisualChanges()
}, completion: { _ in
    self.smyCollectionView.scrollToItem(at: index, at: .centeredHorizontally, animated: true)
})