UICollectionView 部分标题闪烁问题
Posted
技术标签:
【中文标题】UICollectionView 部分标题闪烁问题【英文标题】:UICollectionView section headers flicker issue 【发布时间】:2014-01-30 12:03:28 【问题描述】:由于 ios 7 上的 UICollectionView
存在问题,我连续 8 小时盯着我的电脑(可能是愚蠢的)发了这篇文章(可能是愚蠢的)。
我对@987654323@ 进行了子类化,以便为我的 UICollectionView 数据源的所有 50 个部分提供一个通用的“Section X”(粘性标题)[其中 X 是一个数字]标题,这是一个 NSArray 分区。
我在我的子类中调用- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect
,它确实显示了标题,但仅用于第一部分。这是非常奇怪的行为。我的期望是:
|S| [CELL] [CELL] |S| [CELL] [CELL]
|E| [ ] [ ] |E| [ ] [ ]
|C| [____] [____] |C| [____] [____]
|T| |T|
| | [CELL] [CELL] | | [CELL]
| | [ ] [ ] | | [ ]
|1| [____] [____] |2| [____]
“SECT 2” 是第一个部分之后的下一个部分标题,当用户水平滚动(垂直方向相同)时,应该在屏幕上可见,但是什么我得到的是:
|S| [CELL] [CELL] | | [CELL] [CELL]
|E| [ ] [ ] | | [ ] [ ]
|C| [____] [____] | | [____] [____]
|T| | |
| | [CELL] [CELL] | | [CELL]
| | [ ] [ ] | | [ ]
|2| [____] [____] | | [____]
第一个节标题之后的空白节标题,以及第二个节标题的位置错误。当我滚动 UICollectionView
时,这一切都会改变。第二个在错误的地方消失了,但它也没有去它应该在的地方。
在稍微滚动之后:
|S| [CELL] [CELL] | | [CELL] [CELL]
|E| [ ] [ ] | | [ ] [ ]
|C| [____] [____] | | [____] [____]
|T| | |
| | [CELL] [CELL] | | [CELL]
| | [ ] [ ] | | [ ]
|1| [____] [____] | | [____]
在第 1 节之后仍然是空白。
在我真正滚动到该部分的开头之前,UICollectionView
中的任何部分标题实际上都不可见。它没有滚动到位,而是出现在正确的位置,没有任何动画。我一直在滚动,这是相同的行为。
我已经在没有UICollectionViewFlowLayout
子类的情况下测试了这种行为,只是在屏幕上粘贴了一个通用的UIView
。在 iOS 6 上,这个问题不存在。标题似乎在整个滚动过程中出列并正确显示,没有任何问题。
任何人都可以帮助我,或者其他人在 iOS 7 上给出 UICollectionView
部分标题时遇到过这个问题吗?我疯了!!
layoutAttributesForElementsInRect:
方法
- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect
NSMutableArray *answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
UICollectionView * const cv = self.collectionView;
CGPoint const contentOffset = cv.contentOffset;
NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet];
for (UICollectionViewLayoutAttributes *layoutAttributes in answer)
if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell)
[missingSections addIndex:layoutAttributes.indexPath.section];
for (UICollectionViewLayoutAttributes *layoutAttributes in answer)
if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader])
[missingSections removeIndex:layoutAttributes.indexPath.section];
[missingSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop)
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx];
UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
[answer addObject:layoutAttributes];
];
for (UICollectionViewLayoutAttributes *layoutAttributes in answer)
if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader])
NSInteger section = layoutAttributes.indexPath.section;
NSInteger numberOfItemsInSection = [cv numberOfItemsInSection:section];
NSIndexPath *firstCellIndexPath = [NSIndexPath indexPathForItem:0 inSection:section];
NSIndexPath *lastCellIndexPath = [NSIndexPath indexPathForItem:MAX(0, (numberOfItemsInSection - 1)) inSection:section];
UICollectionViewLayoutAttributes *firstCellAttrs = [self layoutAttributesForItemAtIndexPath:firstCellIndexPath];
UICollectionViewLayoutAttributes *lastCellAttrs = [self layoutAttributesForItemAtIndexPath:lastCellIndexPath];
CGFloat headerWidth = CGRectGetWidth(layoutAttributes.frame);
CGPoint origin = layoutAttributes.frame.origin;
origin.x = MIN(MAX(contentOffset.x, (CGRectGetMinX(firstCellAttrs.frame) - headerWidth)),
(CGRectGetMaxX(lastCellAttrs.frame) - headerWidth)
);
layoutAttributes.zIndex = 1024;
layoutAttributes.frame = (CGRect)
.origin = origin,
.size = layoutAttributes.frame.size
;
return answer;
viewForSupplementaryElementOfKind:
相关代码:
CollectionHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:
UICollectionElementKindSectionHeader withReuseIdentifier:CellIdentifier forIndexPath:indexPath];
headerView.frame = CGRectMake(0, 0, 60, sectionContainerView.frame.size.height);
[headerView setBackgroundColor:[UIColor greenColor]]; //to test visibility
return headerView;
【问题讨论】:
我不知道你的布局有什么问题,但我在uicollectionview-gridlayout 中有一个强大的粘性标题实现,它可能会给你一些指示。或者,如果您想使用它,它目前只进行垂直滚动,但水平将是一个简单的添加。 不幸的是,我不知道如何将 Horizontal 添加到您的子类中,甚至不知道如何使用它。我很抱歉。 我并不是建议您进行更改。 我从 IB 关闭了我的子类,这意味着它使用来自 Apple 的默认流。而且只有一个部分标题,固定在屏幕左侧,其他部分不显示。 【参考方案1】:我解决了我的问题。原来在iOS 7里面
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
您绝不能设置补充视图的框架。将其留给适当的委托方法。
我的天哪。 17 小时后,我要去睡觉。
【讨论】:
以上是关于UICollectionView 部分标题闪烁问题的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionView reloadData 但查看闪烁
UICollectionView多个单元格(UICollectionViewCell)在Objective-C中闪烁同步