Ios 添加到UICollectionView的多个装饰视图
我正在创建一个基本的集合视图布局,其中包含子类Ios 添加到UICollectionView的多个装饰视图,ios,objective-c,ios6,uicollectionview,uicollectionviewlayout,Ios,Objective C,Ios6,Uicollectionview,Uicollectionviewlayout,我正在创建一个基本的集合视图布局,其中包含子类UICollectionViewFlowLayout。然而,我注意到似乎有几个装饰视图堆叠在一起 每当用户在最后一部分中选择一个项目时,我都会添加一个新的部分,代码如下。似乎每当我执行这段代码时,就会向每个已经存在的部分添加装饰视图的一个额外副本 [collectionView performBatchUpdates:^{ currentModelArrayIndex++; [collectionView insertSections
UICollectionViewFlowLayout
。然而,我注意到似乎有几个装饰视图堆叠在一起
每当用户在最后一部分中选择一个项目时,我都会添加一个新的部分,代码如下。似乎每当我执行这段代码时,就会向每个已经存在的部分添加装饰视图的一个额外副本
[collectionView performBatchUpdates:^{
currentModelArrayIndex++;
[collectionView insertSections:[NSIndexSet indexSetWithIndex:currentModelArrayIndex]];
[collectionView reloadSections:[NSIndexSet indexSetWithIndex:currentModelArrayIndex-1]];
} completion:^(BOOL finished) {
[collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:currentModelArrayIndex] atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
}];
我给我的装饰视图提供了alpha
的0.2f
并看到它们堆叠起来,从而证实了这一点
我还执行了集合视图层次结构的转储,看到了10个AFDecorationView
实例,而我应该只看到4个:
| <AFDecorationView: 0x719ee50; baseClass = UICollectionReusableView; frame = (0 65; 768 208.125); alpha = 0; hidden = YES; layer = <CALayer: 0x719eec0>>
| <AFDecorationView: 0x71ad980; baseClass = UICollectionReusableView; frame = (0 333.125; 768 203.281); alpha = 0; hidden = YES; layer = <CALayer: 0x71adb60>>
| <AFDecorationView: 0x71afc90; baseClass = UICollectionReusableView; frame = (0 65; 768 208.125); layer = <CALayer: 0x71afd60>>
| <AFDecorationView: 0xd79ac30; baseClass = UICollectionReusableView; frame = (0 596.406; 768 203.281); alpha = 0; hidden = YES; layer = <CALayer: 0xd79ad00>>
| <AFDecorationView: 0xd79cf20; baseClass = UICollectionReusableView; frame = (0 333.125; 768 203.281); layer = <CALayer: 0xd79cff0>>
| <AFDecorationView: 0xd79dac0; baseClass = UICollectionReusableView; frame = (0 65; 768 208.125); layer = <CALayer: 0xd79a980>>
| <AFDecorationView: 0xd794fd0; baseClass = UICollectionReusableView; frame = (0 859.688; 768 225.938); layer = <CALayer: 0xd7950a0>>
| <AFDecorationView: 0xd7a1300; baseClass = UICollectionReusableView; frame = (0 596.406; 768 203.281); layer = <CALayer: 0xd7a13d0>></CALayer:>
| <AFDecorationView: 0xd7a35d0; baseClass = UICollectionReusableView; frame = (0 65; 768 208.125); layer = <CALayer: 0xd794470>>
| <AFDecorationView: 0xd7a43e0; baseClass = UICollectionReusableView; frame = (0 333.125; 768 203.281); layer = <CALayer: 0xd7a44b0>>
我只希望每个部分有一个装饰视图,所以我将装饰视图添加到第一个部分 这似乎是
UICollectionView
中的一个bug。我已经向苹果公司提交了一份文件。我也有一个类似的问题,但我能够通过手动删除自定义布局类中prepareLayout
中的所有装饰视图来解决它(我在调用[super prepareLayout]
之前就这样做了):
我仍在考虑这一点,但我有两点意见:(a)如果(attributes.indexPath.item==0)为真,您能检查并查看您的
的次数吗?也许还有其他的观点,像其他的补充观点一样,导致它比你预期的更火?(b)在给定的部分中使用第0行单元格来确定是否应该包含装饰单元格似乎有点可笑,因为它们(我假设)占用不同的rect,因此对layouttributesforementsinrect:
的一些调用可能会返回一个而不是另一个。另外:如果只使用reloadData
而不是执行批处理更新,行为是否会改变?不久前,我还遇到了一个集合视图问题。在花了很多时间试图修复它之后,我提交了一份TSI。苹果的工程师告诉我这是一个bug。这似乎是相当多的车…@JesseRusak谢谢你的建议-我会尝试看看你是否正确。您能为indexPath.item==0
提供一个替代方案吗?我的装修视图是每个部分一个。谢谢我已将检查更改为attributes.representedElementCategory==UICollectionElementCategorySupplementaryView
,并添加了日志记录以查看是否添加了多次,但看起来很正常。我认为GuidoH是对的-这只是一辆马车。是的,我认为你是对的。我有一个类似的问题,在内容更新后使用了错误类型的装饰视图,而现有视图没有被删除。这不是我在UICollectionView中看到的唯一一个bug。希望它能在下一个版本中被分类。有类似的问题。UICollectionView在IMHO中未准备好生产。错误太多,尤其是装饰/补充视图。苹果真的把这件事搞砸了。你收到苹果关于这个错误的回复了吗?我有一个类似的问题,补充意见堆积-这一次,当我失效。额外的视图永远不会被删除,当我的布局移动东西时,这会导致真正的问题。这在iOS[修订版]时已经解决-目前没有其他解决办法。我在iOS 8.1.3上遇到了这个错误。在我的例子中,如果我以编程方式设置contentOffset
,就会发生这种情况。
@implementation AFCollectionViewFlowLayout
-(id)init
{
if (!(self = [super init])) return nil;
[self registerClass:[AFDecorationView class] forDecorationViewOfKind:AFCollectionViewFlowLayoutBackgroundDecoration];
return self;
}
#pragma mark - Private Helper Methods
-(void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes
{
//implemented
}
#pragma mark - Overridden Methods
#pragma mark Cell Layout
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributesArray = [super layoutAttributesForElementsInRect:rect];
NSMutableArray *newAttributesArray = [NSMutableArray array];
for (UICollectionViewLayoutAttributes *attributes in attributesArray)
{
[self applyLayoutAttributes:attributes];
if (attributes.indexPath.item == 0)
{
UICollectionViewLayoutAttributes *newAttributes = [self layoutAttributesForDecorationViewOfKind:AFCollectionViewFlowLayoutBackgroundDecoration atIndexPath:attributes.indexPath];
[newAttributesArray addObject:newAttributes];
}
}
attributesArray = [attributesArray arrayByAddingObjectsFromArray:newAttributesArray];
return attributesArray;
}
#pragma mark Decoration View Layout
-(UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath];
if ([decorationViewKind isEqualToString:AFCollectionViewFlowLayoutBackgroundDecoration])
{
UICollectionViewLayoutAttributes *tallestCellAttributes;
NSInteger numberOfCellsInSection = [self.collectionView numberOfItemsInSection:indexPath.section];
for (NSInteger i = 0; i < numberOfCellsInSection; i++)
{
NSIndexPath *cellIndexPath = [NSIndexPath indexPathForItem:i inSection:indexPath.section];
UICollectionViewLayoutAttributes *cellAttribtes = [self layoutAttributesForItemAtIndexPath:cellIndexPath];
if (CGRectGetHeight(cellAttribtes.frame) > CGRectGetHeight(tallestCellAttributes.frame))
{
tallestCellAttributes = cellAttribtes;
}
}
CGFloat decorationViewHeight = CGRectGetHeight(tallestCellAttributes.frame) + self.headerReferenceSize.height;
layoutAttributes.size = CGSizeMake([self collectionViewContentSize].width, decorationViewHeight);
layoutAttributes.center = CGPointMake([self collectionViewContentSize].width / 2.0f, tallestCellAttributes.center.y);
layoutAttributes.zIndex = -1;
}
return layoutAttributes;
}
@end
// Iterate over all subviews to remove all decoration views
for (UIView *view in self.collectionView.subviews)
{
if ([view isKindOfClass:[DecorationView class]])
{
[view removeFromSuperview];
}
}
[super prepareLayout];