在 layoutAttributesForElements 中更改帧会减慢动画速度
Posted
技术标签:
【中文标题】在 layoutAttributesForElements 中更改帧会减慢动画速度【英文标题】:Changing frames in layoutAttributesForElements slow down animation 【发布时间】:2018-01-03 14:47:58 【问题描述】:我有一个自定义的 CollectionViewFlowLayout,我在其中覆盖了layoutAttributesForElements(in rect: CGRect)
,以便让元素按照设计规范进行定位。
一切都很好,但在某些情况下,要制作“选择模式”动画,我需要更新帧的 y 位置,但是当我这样做时,我的动画会有一点延迟。
如果我保持y位置,更新属性的x,宽高,动画就ok了。
为什么会这样?我该如何避免呢?
这是我的布局模型:
这是选择的模式:
基本上,我的动画包括更改可见单元格的变换,以使它们更小但居中,并保持对齐和正确的间距,我在 layoutAttributesForElements 中操作框架并使布局无效。
编辑:
其他解决方案(例如更改 cellSize 和 minimumInteritemSpacing 对我不起作用,因为用于 cellSize 更改的 UICollectionView 动画非常不稳定【问题讨论】:
我不是你如何为这个布局更改设置动画,但我能够通过适当地更改项目大小并在动画块中调用 invalidateLayout() 来获得非常流畅的实现。看起来你做的工作比你需要做的要多。我在这里做了一个测试项目github.com/edmonston/test-cvlo 这是一个视频github.com/edmonston/test-cvlo/blob/master/demo.mov?raw=true 看起来不错,我试试这个 它有点工作,但它不能解决我原来的问题。您只能更改项目之间的间距,而不是屏幕边缘的间距。我修改了您的代码以设置 UICollectionView 的 contentInset,但现在我必须从 cellSize 中删除该 inset,否则会破坏布局。在您的示例中,计算很简单,但就我而言,当时我不知道每行有多少个单元格,因此我无法计算并返回正确的项目大小。这就是为什么我使用自定义 UICollectionViewFlowLayout 忘记我所说的几乎所有内容,我确实有每行的单元格数量,我对您的想法做了一些进一步的更改,但现在效果很好!我必须扔掉所有自定义 UICollectionViewFlowLayout 代码,谢谢! 请添加答案,以便我接受 【参考方案1】:正如我在 cmets 中提到的,似乎有一个更简单的方法:我能够通过适当地更改从 collectionView(_:layout:sizeForItemAt:)
、collectionView(_:layout:minimumLineSpacingForSectionAt:)
和 collectionView(_:minimumInteritemSpacingForSectionAt:)
返回的值来获得一个非常顺利的实现,并且在适当的时候在动画块内调用invalidateLayout()
和layoutIfNeeded()
。
一个非常基本的项目布局的返回值可能如下所示(separatorSize(isInSelectionMode:)
根据选择状态返回更大或更小的值):
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 和一个demo video here。
【讨论】:
以上是关于在 layoutAttributesForElements 中更改帧会减慢动画速度的主要内容,如果未能解决你的问题,请参考以下文章
NOIP 2015 & SDOI 2016 Round1 & CTSC 2016 & SDOI2016 Round2游记