代理設(shè)計(jì)模式的組成
客戶類(lèi)(通常作為代理)
真實(shí)角色
代理協(xié)議
代理角色
文字描述通常是抽象的,一下通過(guò)圖示來(lái)闡述代理設(shè)計(jì)模式
業(yè)務(wù)邏輯
如圖
布局每個(gè)cell的業(yè)務(wù)邏輯
由于設(shè)置每個(gè)cell的布局屬性的業(yè)務(wù)邏輯較復(fù)雜,特附上如下思維導(dǎo)圖
封裝思路封裝需要根據(jù)客戶類(lèi)業(yè)務(wù)邏輯需求來(lái)提供接口
自定義布局提供的接口可選
自定義布局提供的接口必選
設(shè)置代理協(xié)議,提供接口
//聲明LYPWaterFlowLayout為一個(gè)類(lèi)@class LYPWaterFlowLayout;@PRotocol LYPWaterFlowLayoutDelegate <NSObject>//必須實(shí)現(xiàn)的方法@required/**獲取瀑布流每個(gè)元素的高度*/- (CGFloat)waterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout heightForItemAtIndex:(NSInteger)index itemWith:(CGFloat)itemWith;//可選實(shí)現(xiàn)的方法@optional/**獲取瀑布流的列數(shù)*/- (NSInteger)columnCountInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout;/**獲取瀑布流列間距*/- (CGFloat)columnMarginInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout;/**獲取瀑布流的行間距*/- (CGFloat)rowMarginInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout;/**獲取瀑布流的內(nèi)邊距*/- (UIEdgeInsets)edgeInsetsInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout;@end
設(shè)置代理屬性
@interface LYPWaterFlowLayout : UICollectionViewLayout/**代理*/@property (nonatomic, weak) id<LYPWaterFlowLayoutDelegate> delegate;@end
設(shè)置通過(guò)可選代理方法獲取屬性值的屬性的默認(rèn)值
/**默認(rèn)的列數(shù)*/static const NSInteger LYPDefaultColumnCount = 3;/**默認(rèn)每一列之間的間距*/static const CGFloat LYPDefaultColumMargin = 10;/**默認(rèn)每一行之間的間距*/static const CGFloat LYPDefaultRowMargin = 10;/**默認(rèn)邊緣間距*/static const UIEdgeInsets LYPDefaultEdgeInsets = {10, 10, 10, 10};
設(shè)置通過(guò)可選代理方法獲取屬性值的屬性的訪問(wèn)方式若代理提供屬性值,則忽略默認(rèn)值
- (NSInteger)columnCount{ //判斷代理是否實(shí)現(xiàn)了獲取列數(shù)的可選方法 if ([self.delegate respondsToSelector:@selector(columnCountInWaterFlowLayout:)]) { //實(shí)現(xiàn),返回通過(guò)代理設(shè)置的列數(shù) return [self.delegate columnCountInWaterFlowLayout:self]; } else { //為實(shí)現(xiàn),返回默認(rèn)的列數(shù) return LYPDefaultColumnCount; }}
設(shè)置布局
設(shè)置需要的成員屬性
/**所有cell的布局屬性*/@property (nonatomic, strong) NSMutableArray *attrsArray;/**所有列的當(dāng)前高度*/@property (nonatomic, strong) NSMutableArray *columnHeights;
通過(guò)懶加載的方式初始化成員屬性
/**--attrsArray--懶加載*/- (NSMutableArray *)attrsArray{ if (_attrsArray == nil) { _attrsArray = [NSMutableArray array]; } return _attrsArray;}/**--columnHeights--懶加載*/- (NSMutableArray *)columnHeights{ if (_columnHeights == nil) { _columnHeights = [NSMutableArray array]; } return _columnHeights;}
初始化布局
- (void)prepareLayout{ [super prepareLayout]; /**清除之前跟布局相關(guān)的所有屬性,重新設(shè)置新的布局*/ //清除之前計(jì)算的所有列的高度 [self.columnHeights removeAllObjects]; //設(shè)置所有列的初始高度 for (NSInteger i = 0; i<self.columnCount; i++) { self.columnHeights[i] = @(self.edgeInsets.top); } //清除之前所有的布局屬性 [self.attrsArray removeAllObjects]; /**開(kāi)始創(chuàng)建每一個(gè)cell對(duì)應(yīng)的布局屬性*/ NSInteger count = [self.collectionView numberOfItemsInSection:0]; for (NSInteger i = 0; i<count; i++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; //獲取indexPath位置cell對(duì)應(yīng)的布局屬性 UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath]; //將indexPath位置的cell的布局屬性添加到所有cell的布局屬性數(shù)組中 [self.attrsArray addObject:attrs]; }}
返回包含所有cell的布局屬性的數(shù)組
- (nullable NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ return self.attrsArray;}
設(shè)置每一個(gè)cell的布局屬性
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(nonnull NSIndexPath *)indexPath{ //獲取indexPath位置的布局屬性 UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; /**設(shè)置cell布局屬性的frame*/ /***確定cell的尺寸***/ //獲取collectionView的寬度 CGFloat collectionViewWidth = self.collectionView.frame.size.width; //cell寬度 CGFloat width = ((collectionViewWidth - self.edgeInsets.left - self.edgeInsets.right - (self.columnCount - 1) * self.columMargin)) / self.columnCount; //cell高度 CGFloat height = [self.delegate waterFlowLayout:self heightForItemAtIndex:indexPath.item itemWith:width]; /***設(shè)置cell的位置***/ NSInteger destColumn = 0; CGFloat minColumnHeight = [self.columnHeights[0] doubleValue]; for (NSInteger i = 1; i<self.columnCount; i++) { CGFloat columnHeight = [self.columnHeights[i] doubleValue]; if (minColumnHeight > columnHeight) { minColumnHeight = columnHeight; destColumn = i; } } //計(jì)算cell的位置 CGFloat x = self.edgeInsets.left + destColumn * (width + self.columMargin); CGFloat y = minColumnHeight; //判斷是不是第一行 if (y != self.edgeInsets.top) { //若不是第一行,需要加上行間距 y += self.rowMargin; } /**給cell的布局屬性的frame賦值*/ attrs.frame = CGRectMake(x, y, width, height); //更新最短那列的高度 self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame)); /**返回indexPath位置的cell的布局屬性*/ return attrs;}
設(shè)置collectionView內(nèi)容的尺寸
- (CGSize)collectionViewContentSize{ //獲取最高的那一列的高度 CGFloat maxColumnHeight = [self.columnHeights[0] doubleValue]; for (NSInteger i = 1; i<self.columnCount; i++) { CGFloat columnHeight = [self.columnHeights[i] doubleValue]; if (maxColumnHeight < columnHeight) { maxColumnHeight = columnHeight; } } //返回collectionView的contentSize,高度為最高的高度加上一個(gè)行間距 return CGSizeMake(0, maxColumnHeight + self.rowMargin);}
|
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注