【问题标题】:UICollectionView: set new layout and target content offsetUICollectionView:设置新布局和目标内容偏移
【发布时间】:2013-06-19 10:26:42
【问题描述】:

我有一个UICollectionView 和两个UICollectionViewFlowLayout 的子类。当一个单元格被选中时,我调用setCollectionViewLayout:animated: 在布局之间切换。过渡完成后,选中的单元格居中即可。

是否可以在不实际选中单元格的情况下完成相同的居中行为?我试过用不同的方法打电话给setContentOffset:animated:,但没有成功。或者,我可以为要显示的布局指定一个自定义的contentOffset 吗?

更清楚地说,我希望在不修改单元格的selected 属性的情况下拥有这样的东西:

编辑 #1

这是我已经拥有的:

[self.collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
[self.collectionView setCollectionViewLayout:layout animated:YES];

看起来不错:https://www.dropbox.com/s/9u6cnwwdbe9vss0/17249646-0.mov


但是如果我跳过selectItemAtIndexPath:

[self.collectionView setCollectionViewLayout:layout animated:YES];
[self.collectionView scrollRectToVisible:targetFrame animated:YES];

这不是很好(一种挥舞的动画):https://www.dropbox.com/s/s3u2eqq16tmex1v/17249646-1.mov

【问题讨论】:

  • 是不是第二种情况下单元格最终过高的问题?我想到了几件事。首先,您可能会受到这个issue with contentOffset 的影响。里面的建议可能会对你有所帮助。其次,您是否验证了传递给scrollRectToVisible 的帧是否实际可见?了解这一点可能有助于缩小解决方案的范围。
  • 如果您查看第二个视频,您可以看到 contentOffset 有点“摇摆”。我上下移动,直到它到达它的最终位置。同时,在第一个视频中只有一个直线运动。问题是,我无法重现!
  • 我注意到两个视频中的最终位置不同。因此,您传递给 scrollRectToVisible 的框架可能不正确。我建议修改那个框架,直到你得到相同的最终位置,看看是否有帮助。
  • 另外,您能否检查contentSizecontentOffset 的最终值和单元格的框架,以验证两个场景之间的所有值是否匹配?
  • 但它不应该与我指定的任何矩形一起使用吗?我的意思是,不限于使用完全居中的矩形。我猜setCollectionViewLayoutscrollRectToVisible 的动画块不知何故发生了冲突,这导致了挥动的东西。你怎么看?

标签: ios objective-c cocoa-touch uicollectionview uicollectionviewlayout


【解决方案1】:

编辑(进一步澄清后更改答案)

我对表格视图 here 做了类似的事情。基本上,您调用scrollRectToVisible:animated: 计算一个矩形,该矩形会将您的滚动视图定位在您希望它结束​​的位置。对于精确定位,我认为您只需要计算与您的视图大小相同的矩形。请注意,如果内容大小将发生变化,则应以预期的最终内容大小计算矩形。

原始答案

您可以修改由超类生成的布局,方法是使用以下内容覆盖 layoutAttributesForElementsInRect:rect

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray *poses = [super layoutAttributesForElementsInRect:rect];
    if (<test whether we want to modify poses>) {
        UICollectionViewLayoutAttributes *pose = poses[<index of pose to be modified>];
        pose.frame = <some other frame>;//modify the frame, for example
    }
    return poses;
}

您还需要使用类似的逻辑覆盖layoutAttributesForItemAtIndexPath。下一步是在您希望更改发生时使布局无效或替换。您还需要传递一些信息。布局需要知道要做什么,因此您可以将相关数据传递给它或扩展UICollectionViewDelegateFlowLayout1

【讨论】:

  • 我不想修改单元格的(姿势)框架。我只想在布局切换时在集合视图上设置一个新的内容偏移量。所以基本上,就像同时调用 setCollectionViewLayout:animated: 和 setContentOffset:animated: 一样。
  • 感谢您的编辑,我也编辑了问题。看看吧!
  • 我又看了一些,波浪运动肯定是由两个独立的动画运行不同的持续时间引起的。但是,全速时效果真的很明显吗?如果你真的想修复它,你可以使用 CADisplayLink(而不是scrollRectToVisible)在动画的每一步显式控制 contentOffset 以强制事物沿直线移动。但这对我来说似乎有点矫枉过正,因为事情在各州之间进展顺利。
  • 是的,它在全速运行时非常明显且令人不安。如果没有解决方法,我将坚持使用 selected 属性。
猜你喜欢
  • 2021-07-04
  • 1970-01-01
  • 2011-04-01
  • 2015-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多