更改 layoutAttributesForElements 中的帧会减慢动画速度
Changing frames in layoutAttributesForElements slow down animation
我有一个自定义的 CollectionViewFlowLayout,我在其中重写了 layoutAttributesForElements(in rect: CGRect)
以使元素按照设计规范定位。
一切都很好,但在某些情况下,要制作 "selection mode" 动画,我需要更新帧的 y 位置,但是当我这样做时,我的动画会出现小的延迟。
如果我保持 y 位置并更新属性的 x、宽度和高度,动画就可以了。
为什么会这样?我该如何避免呢?
这是我的布局模型:
这是选择的模式:
基本上我的动画包括更改可见单元格的变换,使它们更小但居中,并保持对齐和正确的间距我操纵 layoutAttributesForElements 中的帧并使布局无效。
编辑:
- 更改 cellSize 和 minimumInteritemSpacing 等其他解决方案对我不起作用,因为更改 cellSize 的 UICollectionView 动画非常不稳定
正如我在评论中提到的那样,似乎有一种更简单的方法:我只需更改 collectionView(_:layout:sizeForItemAt:)
、collectionView(_:layout:minimumLineSpacingForSectionAt:)
和 collectionView(_:minimumInteritemSpacingForSectionAt:)
,并在适当的时候在动画块中调用 invalidateLayout()
和 layoutIfNeeded()
。
真正基本的项目布局的 return 值可能如下所示(其中 separatorSize(isInSelectionMode:)
return 的值更大或更小,具体取决于选择状态):
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let totalRowHeight: CGFloat = 100
let widthRatio: CGFloat
switch indexPath.item % 4 {
case 0, 3: widthRatio = (2.0 / 3.0)
case 1, 2: widthRatio = (1.0 / 3.0)
default: widthRatio = 1.0
}
return CGSize(width: (collectionView.bounds.width - separatorSize(isInSelectionMode: selectionMode).width) * widthRatio,
height: totalRowHeight - separatorSize(isInSelectionMode: selectionMode).height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return separatorSize(isInSelectionMode: selectionMode).height
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return separatorSize(isInSelectionMode: selectionMode).width
}
然后您只需在动画块内切换 selectionMode
,同时使布局无效。
我做了一个demo project here and a demo video here.
我有一个自定义的 CollectionViewFlowLayout,我在其中重写了 layoutAttributesForElements(in rect: CGRect)
以使元素按照设计规范定位。
一切都很好,但在某些情况下,要制作 "selection mode" 动画,我需要更新帧的 y 位置,但是当我这样做时,我的动画会出现小的延迟。
如果我保持 y 位置并更新属性的 x、宽度和高度,动画就可以了。
为什么会这样?我该如何避免呢?
这是我的布局模型:
这是选择的模式:
基本上我的动画包括更改可见单元格的变换,使它们更小但居中,并保持对齐和正确的间距我操纵 layoutAttributesForElements 中的帧并使布局无效。
编辑:
- 更改 cellSize 和 minimumInteritemSpacing 等其他解决方案对我不起作用,因为更改 cellSize 的 UICollectionView 动画非常不稳定
正如我在评论中提到的那样,似乎有一种更简单的方法:我只需更改 collectionView(_:layout:sizeForItemAt:)
、collectionView(_:layout:minimumLineSpacingForSectionAt:)
和 collectionView(_:minimumInteritemSpacingForSectionAt:)
,并在适当的时候在动画块中调用 invalidateLayout()
和 layoutIfNeeded()
。
真正基本的项目布局的 return 值可能如下所示(其中 separatorSize(isInSelectionMode:)
return 的值更大或更小,具体取决于选择状态):
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let totalRowHeight: CGFloat = 100
let widthRatio: CGFloat
switch indexPath.item % 4 {
case 0, 3: widthRatio = (2.0 / 3.0)
case 1, 2: widthRatio = (1.0 / 3.0)
default: widthRatio = 1.0
}
return CGSize(width: (collectionView.bounds.width - separatorSize(isInSelectionMode: selectionMode).width) * widthRatio,
height: totalRowHeight - separatorSize(isInSelectionMode: selectionMode).height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return separatorSize(isInSelectionMode: selectionMode).height
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return separatorSize(isInSelectionMode: selectionMode).width
}
然后您只需在动画块内切换 selectionMode
,同时使布局无效。
我做了一个demo project here and a demo video here.