一、UICollectionViewLayout基礎(chǔ)知識
- 如果要自定義UICollectionViewLayout,需要實(shí)現(xiàn)以下幾個(gè)方法,按初始化layout后,系統(tǒng)執(zhí)行順序排列:
// 初始化layout后自動(dòng)調(diào)動(dòng),可以在該方法中初始化一些自定義的變量參數(shù)
- (void)prepareLayout;
// 設(shè)置UICollectionView的內(nèi)容大小,道理與UIScrollView的contentSize類似
- (CGSize)collectionViewContentSize;
// 初始Layout外觀,返回所有的布局屬性
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;
// 根據(jù)不同的indexPath,給出布局
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
二、瀑布流布局
邏輯其實(shí)很簡單,就是給出每一個(gè)cell的坐標(biāo)。想要定位一個(gè)控件,需要CGRectMake四個(gè)參數(shù):
y : 首先我們看到的這個(gè)demo是兩列的,所以肯定有兩個(gè)Y軸起始點(diǎn),分為左側(cè)和右側(cè)。
x : 然后除Y軸不同外,左側(cè)和右側(cè)的X軸也不相同。
width : 關(guān)于width我們可以通過一行兩列,然后每一個(gè)cell的間距來得到。
height: height是在collectionView中定義的,layout獲得不到,所以我們選擇用代理,在collectionView中設(shè)置。
@property (assign, nonatomic) CGFloat leftY; // 左側(cè)起始Y軸
@property (assign, nonatomic) CGFloat rightY; // 右側(cè)起始Y軸
@property (assign, nonatomic) NSInteger cellCount; // cell個(gè)數(shù)
@property (assign, nonatomic) CGFloat itemWidth; // cell寬度
@property (assign, nonatomic) CGFloat insert; // 間距
@class WaterfallFlowLayout;
@protocol WaterfallFlowLayoutDelegate <NSObject>
@required
- (CGSize)collectionView:(UICollectionView *)collectionView collectionViewLayout:(sWaterfallFlowLayout *)collectionViewLayout sizeOfItemAtIndexPath:(NSIndexPath *)indexPath;
@end
/**
* 初始化layout后自動(dòng)調(diào)動(dòng),可以在該方法中初始化一些自定義的變量參數(shù)
*/
- (void)prepareLayout {
[super prepareLayout];
// 初始化參數(shù)
_cellCount = [self.collectionView numberOfItemsInSection:0]; // cell個(gè)數(shù),直接從collectionView中獲得
_insert = 10; // 設(shè)置間距
_itemWidth = (SCREEN_WIDTH - 3 * _insert) / 2; // cell寬度
}
/**
* 設(shè)置UICollectionView的內(nèi)容大小,道理與UIScrollView的contentSize類似
* @return 返回設(shè)置的UICollectionView的內(nèi)容大小
*/
- (CGSize)collectionViewContentSize {
return CGSizeMake(SCREEN_WIDTH, MAX(_leftY, _rightY));
}
/**
* 初始Layout外觀
* @param rect 所有元素的布局屬性
* @return 所有元素的布局
*/
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
_leftY = _insert; // 左邊起始Y軸
_rightY = _insert; // 右邊起始Y軸
NSMutableArray *attributes = [[NSMutableArray alloc] init];
for (int i = 0; i < self.cellCount; i ++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
}
return attributes;
}
/**
* 根據(jù)不同的indexPath,給出布局
* @param indexPath
* @return
*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
// 獲取代理中返回的每一個(gè)cell的大小
CGSize itemSize = [self.delegate collectionView:self.collectionView collectionViewLayout:self sizeOfItemAtIndexPath:indexPath];
// 防止代理中給的size.width大于(或小于)layout中定義的width,所以等比例縮放size
CGFloat itemHeight = floorf(itemSize.height * self.itemWidth / itemSize.width);
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
// 判斷當(dāng)前的item應(yīng)該在左側(cè)還是右側(cè)
BOOL isLeft = _leftY < _rightY;
if (isLeft) {
CGFloat x = _insert;
attributes.frame = CGRectMake(x, _leftY, _itemWidth, itemHeight);
_leftY += itemHeight + _insert; // 設(shè)置新的Y起點(diǎn)
} else {
CGFloat x = _itemWidth + 2 * _insert;
attributes.frame = CGRectMake(x, _rightY, _itemWidth, itemHeight);
_rightY += itemHeight + _insert;
}
return attributes;
}
Demo地址
https://github.com/shawenlx/WaterfallFlowCollection
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。