已更新Demo(2017-8-8):
https://pan.baidu.com/s/1bDXrYI
不放github了
下面這種需求應(yīng)該是會經(jīng)常遇到的:
需求:固定高度一個區(qū)域独令,里面左右分頁顯示很多個圖標(biāo)赶促,在每一頁中的圖標(biāo)先從左往右排,排滿后再從上往下排慨菱。這一頁排滿后排下一頁焰络。
圖中這樣的:上面cell的順序我已經(jīng)標(biāo)出來了。
像這樣的需求符喝,第一反應(yīng)是用UICollectionView來寫闪彼,用UICollectionViewFlowLayout,然后設(shè)置為橫向的协饲。但是畏腕,采用這種方式來寫,出來的效果就會是這樣的:
那么還可以怎么實現(xiàn)茉稠?可以用大的cell包5個小圖標(biāo)在里面描馅。這樣實現(xiàn)按說沒問題,但是如果單個圖標(biāo)這里復(fù)雜一點而线,就需要調(diào)很久了铭污,而且如果要根據(jù)屏幕尺寸來定每行顯示的圖標(biāo)個數(shù)也很麻煩恋日。
下面是我的實現(xiàn):
子類化 UICollectionViewFlowLayout
DDCollectionViewHorizontalLayout.h
@interface DDCollectionViewHorizontalLayout : UICollectionViewFlowLayout
// 一行中 cell的個數(shù)
@property (nonatomic) NSUInteger itemCountPerRow;
// 一頁顯示多少行
@property (nonatomic) NSUInteger rowCount;
@end
DDCollectionViewHorizontalLayout.m
@interface DDCollectionViewHorizontalLayout ()
@property (strong, nonatomic) NSMutableArray *allAttributes;
@end
- (void)prepareLayout
{
[super prepareLayout];
self.allAttributes = [NSMutableArray array];
NSUInteger count = [self.collectionView numberOfItemsInSection:0];
for (NSUInteger i = 0; i<count; i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
[self.allAttributes addObject:attributes];
}
}
- (CGSize)collectionViewContentSize
{
return [super collectionViewContentSize];
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger item = indexPath.item;
NSUInteger x;
NSUInteger y;
[self targetPositionWithItem:item resultX:&x resultY:&y];
NSUInteger item2 = [self originItemAtX:x y:y];
NSIndexPath *theNewIndexPath = [NSIndexPath indexPathForItem:item2 inSection:indexPath.section];
UICollectionViewLayoutAttributes *theNewAttr = [super layoutAttributesForItemAtIndexPath:theNewIndexPath];
theNewAttr.indexPath = indexPath;
return theNewAttr;
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
NSMutableArray *tmp = [NSMutableArray array];
for (UICollectionViewLayoutAttributes *attr in attributes) {
for (UICollectionViewLayoutAttributes *attr2 in self.allAttributes) {
if (attr.indexPath.item == attr2.indexPath.item) {
[tmp addObject:attr2];
break;
}
}
}
return tmp;
}
// 根據(jù) item 計算目標(biāo)item的位置
// x 橫向偏移 y 豎向偏移
- (void)targetPositionWithItem:(NSUInteger)item
resultX:(NSUInteger *)x
resultY:(NSUInteger *)y
{
NSUInteger page = item/(self.itemCountPerRow*self.rowCount);
NSUInteger theX = item % self.itemCountPerRow + page * self.itemCountPerRow;
NSUInteger theY = item / self.itemCountPerRow - page * self.rowCount;
if (x != NULL) {
*x = theX;
}
if (y != NULL) {
*y = theY;
}
}
// 根據(jù)偏移量計算item
- (NSUInteger)originItemAtX:(NSUInteger)x
y:(NSUInteger)y
{
NSUInteger item = x * self.rowCount + y;
return item;
}
@end
需要注意的
我這個簡單的實現(xiàn)只支持1個section,而且section的items個數(shù)必須是 itemCountPerRow * rowCount 的整數(shù)倍嘹狞。這里需要在UICollectionView的代理里面做好數(shù)組越界檢查岂膳,防止數(shù)組越界造成崩潰。
完整的實現(xiàn)以后再說吧磅网,現(xiàn)在這樣已經(jīng)滿足需求了谈截。