UICollectionView自定义行分隔符
我想在 UICollectionView
中为我们的新应用制作 2pt黑色分隔符。我们的应用程序截图如下。我们无法使用 UITableView
,因为我们有自定义插入/删除动画,滚动和视差效果等等。
I wanna making 2pt black separators in UICollectionView
for our new app. Screenshot from our app is below. We couldn't use UITableView
, because we have custom insert/delete animations, scrolling and parallax effects and so on.
我从三个想法开始如何制作它:
I started with three ideas how to make it:
- 在单元格中实现这些分隔符
- 使用纯黑色背景和
minimumLineSpacing
,因此我们会在单元格之间的空格中看到背景 - 使用自定义布局并将此分隔符实现为装饰
- implement these separators right inside the cells
- use solid black background with
minimumLineSpacing
, thus we will see background in spaces between cells - use custom layout and implement this separators as decorations
前两个变体被拒绝是因为意识形态不一致,自定义动画以及收集下面的内容。此外,我已经有了自定义布局。
First two variants were rejected because ideologic inconsistency, custom animations and having content below collection. Also I already have a custom layout.
我将描述使用 UICollectionViewFlowLayout
的自定义子类的步骤。
I will describe the steps with a custom subclass of UICollectionViewFlowLayout
.
实施自定义 UICollectionReusableView
子类。
@interface FLCollectionSeparator : UICollectionReusableView
@end
@implementation FLCollectionSeparator
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor blackColor];
}
return self;
}
- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
self.frame = layoutAttributes.frame;
}
@end
- 2 -
说布局使用自定义装饰。还要在单元格之间建立行间距。
--2--
Say layout to use custom decorations. Also make line spacing between cells.
UICollectionViewFlowLayout* layout = (UICollectionViewFlowLayout*) self.newsCollection.collectionViewLayout;
[layout registerClass:[FLCollectionSeparator class] forDecorationViewOfKind:@"Separator"];
layout.minimumLineSpacing = 2;
- 3 -
In自定义 UICollectionViewFlowLayout
子类我们应该从 layoutAttributesForElementsInRect
返回装饰 UICollectionViewLayoutAttributes
。
--3--
In custom UICollectionViewFlowLayout
subclass we should return UICollectionViewLayoutAttributes
for decorations from layoutAttributesForElementsInRect
.
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
... collect here layout attributes for cells ...
NSMutableArray *decorationAttributes = [NSMutableArray array];
NSArray *visibleIndexPaths = [self indexPathsOfSeparatorsInRect:rect]; // will implement below
for (NSIndexPath *indexPath in visibleIndexPaths) {
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForDecorationViewOfKind:@"Separator" atIndexPath:indexPath];
[decorationAttributes addObject:attributes];
}
return [layoutAttributesArray arrayByAddingObjectsFromArray:decorationAttributes];
}
- 4 -
对于可见的rect,我们应该返回可见的装饰索引pathes。
--4--
For visible rect we should return visible decorations index pathes.
- (NSArray*)indexPathsOfSeparatorsInRect:(CGRect)rect {
NSInteger firstCellIndexToShow = floorf(rect.origin.y / self.itemSize.height);
NSInteger lastCellIndexToShow = floorf((rect.origin.y + CGRectGetHeight(rect)) / self.itemSize.height);
NSInteger countOfItems = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];
NSMutableArray* indexPaths = [NSMutableArray new];
for (int i = MAX(firstCellIndexToShow, 0); i <= lastCellIndexToShow; i++) {
if (i < countOfItems) {
[indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
}
return indexPaths;
}
- 5 -
我们还应该实现 layoutAttributesForDecorationViewOfKind
。
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath];
CGFloat decorationOffset = (indexPath.row + 1) * self.itemSize.height + indexPath.row * self.minimumLineSpacing;
layoutAttributes.frame = CGRectMake(0.0, decorationOffset, self.collectionViewContentSize.width, self.minimumLineSpacing);
layoutAttributes.zIndex = 1000;
return layoutAttributes;
}
- 6 -
有时我发现这个解决方案给出了装饰外观的视觉故障,通过实现 initialLayoutAttributesForAppearingDecorationElementOfKind
来修复。
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath {
UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForDecorationViewOfKind:elementKind atIndexPath:decorationIndexPath];
return layoutAttributes;
}
这就是全部。没有太多的代码,但做得很好。
That's all. Not too much code but done right.