自定义 UICollectionViewFlowLayout 问题
Posted
技术标签:
【中文标题】自定义 UICollectionViewFlowLayout 问题【英文标题】:Custom UICollectionViewFlowLayout issue 【发布时间】:2013-03-05 00:01:49 【问题描述】:我有一个带有子类 UICollectionViewFlow 布局的集合视图。 我想要的效果是旋转(透视,圆形 y 轴)和运动缩放。 我的集合视图设置为分页模式,水平滚动,每个单元格都有全屏,即它们的框架等于集合视图的边界。每个单元格内部都有一个表格视图。
问题是我的行为很奇怪。当前在屏幕上的单元格内的表格很好。当我平移到另一个单元格时,问题就出现了。单元格内的表格似乎完全错误!它只填满了单元格的一半,即使单元格要大得多。在界面构建器中,我将表格设置为将其边缘粘贴到其超级视图(单元格)边缘(自动布局)。
一段时间后,我发现 [cell layoutsubviews] 仅在视图实例化后被调用一次。由于我在下面的代码中直接设置 UICollectionViewLayoutAttributes 与旋转,表视图是否可以在考虑初始旋转的情况下进行布局(超级视图的框架由于严重的透视旋转而缩小)并且因为 [cell layoutsubiews] 永远不会再次调用它就一直这样?
第二个奇怪的地方是布局的回调没有意义。 集合视图:didEndDisplayingCell:forItemAtIndexPath: 例如,告诉我索引路径处的视图已停止显示,甚至在它出现在屏幕上之前!
有人可以尝试这种布局,也许可以告诉我我做错了什么?
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
return YES;
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
NSArray* array = [super layoutAttributesForElementsInRect:rect];
CGRect visibleRect;
visibleRect.origin = self.collectionView.contentOffset;
visibleRect.size = self.collectionView.bounds.size;
for (UICollectionViewLayoutAttributes* attributes in array)
if (CGRectIntersectsRect(visibleRect, attributes.frame) &&
ABS(CGRectGetMidX(visibleRect) - attributes.center.x) <= self.collectionView.frame.size.width)
CGFloat distance = CGRectGetMidX(visibleRect) - attributes.center.x;
CGFloat absoluteDistance = ABS(distance);
CGFloat angle = [self normalizeFromMin:0
fromMax:self.collectionView.frame.size.width
toMin:0
toMax:90
value:absoluteDistance];
CGFloat scale = [self normalizeFromMin:0
fromMax:self.collectionView.frame.size.width
toMin:0.7
toMax:1
value:absoluteDistance];
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -1800;
if(distance > 0)
transform = CATransform3DRotate(transform, radians(angle), 0.0, 1.0, 0.0);
else
transform = CATransform3DRotate(transform, -radians(angle), 0.0, 1.0, 0.0);
transform = CATransform3DScale(transform, 1.0 - scale, 1.0 - scale, 0.0);
attributes.transform3D = transform;
attributes.alpha = 1.0;
if(distance == 0)
attributes.zIndex = 1;
attributes.transform3D = CATransform3DIdentity;
else
attributes.zIndex = 0;
return array;
-(CGFloat)normalizeFromMin:(CGFloat)fromMin
fromMax:(CGFloat)fromMax
toMin:(CGFloat)toMin
toMax:(CGFloat)toMax
value:(CGFloat)toNormalize
CGFloat toBeDivided = toMin + (toNormalize - fromMin) * (toMax - toMin);
CGFloat result = toBeDivided / (fromMax - fromMin);
return result;
编辑:
添加
attributes.frame = attributes.frame
在宽度方面似乎有点帮助,但里面的表格似乎没有正确布局。看起来大小是正确的,但在旋转时,单元格只是夹住了表格,但表格本身看起来很奇怪,就像没有应用旋转一样,
【问题讨论】:
【参考方案1】:部分修复:
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
CGRect visibleRect;
visibleRect.origin = self.collectionView.contentOffset;
visibleRect.size = self.collectionView.bounds.size;
NSArray *paths = [self.collectionView indexPathsForVisibleItems];
[paths enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
UICollectionViewCell *cell =b[self.collectionView cellForItemAtIndexPath:obj];
[cell.contentView.subviews[0] setFrame:cell.contentView.bounds];
];
如果我将我的控制器设置为该方法的集合视图的委托,它似乎确实有效,但我希望自动布局能够启动并为我完成。 [cell.contentView setNeedsLayout] / [cell.contentView layoutIfNeeded] 不起作用。
【讨论】:
以上是关于自定义 UICollectionViewFlowLayout 问题的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionViewDelegateFlowLayout UICollectionViewFlowLayout 的区别
尽管实现了 sizeForItemAt,但 UICollectionViewFlowLayout 单元格大小永远不会改变