自定義UICollectionViewLayout
效果如圖:
自定義UICollectionViewLayout 除了計算比較麻煩,其他控制還蠻方便
先貼關鍵程式碼,等有時間在寫註釋:
@interface WMTopUpLayout ()
/** 包含 header 和 footer */
@property (nonatomic, strong) NSMutableArray *layoutInfoArray;
/** 不包含 header 和 footer */
@property (nonatomic, strong) NSMutableArray *itemLayoutInfoArray;
@property (nonatomic, assign) CGSize contentSize;
@end
@implementation WMTopUpLayout
- (NSMutableArray *)layoutInfoArray {
if (!_layoutInfoArray) {
_layoutInfoArray = [[NSMutableArray alloc] init];
}
return _layoutInfoArray;
}
- (NSMutableArray *)itemLayoutInfoArray {
if (!_itemLayoutInfoArray) {
_itemLayoutInfoArray = [[NSMutableArray alloc] init];
}
return _itemLayoutInfoArray;
}
/**
The collection view calls -prepareLayout once at its first layout as the first message to the layout instance.
The collection view calls -prepareLayout again after layout is invalidated and before requerying the layout information.
Subclasses should always call super if they override.
*/
- (void)prepareLayout {
[super prepareLayout];
[self.layoutInfoArray removeAllObjects];
[self.itemLayoutInfoArray removeAllObjects];
NSInteger numberOfSection = [self.collectionView numberOfSections];
for (int section = 0; section < numberOfSection; section ++) {
NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:section];
NSMutableArray *tmp_layoutArray = [NSMutableArray array];
NSMutableArray *tmp_itemArray = [NSMutableArray array];
if (section == 2 && numberOfItems > 0) {
UICollectionViewLayoutAttributes *headerAttr = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
[tmp_layoutArray addObject:headerAttr];
}
for (int item = 0; item < numberOfItems; item ++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:item inSection:section];
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
[tmp_layoutArray addObject:attributes];
[tmp_itemArray addObject:attributes];
}
if (section == 3 && numberOfItems > 0) {
UICollectionViewLayoutAttributes *footerAttr = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter atIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
[tmp_layoutArray addObject:footerAttr];
}
// 把每一個section的每一個item的佈局資訊新增陣列
if (tmp_layoutArray.count > 0) {
[self.layoutInfoArray addObject:tmp_layoutArray];
}
if (tmp_itemArray.count > 0) {
[self.itemLayoutInfoArray addObject:tmp_itemArray];
}
}
UICollectionViewLayoutAttributes *attri = [[self.layoutInfoArray lastObject] lastObject];
self.contentSize = CGSizeMake(_width_, CGRectGetMaxY(attri.frame));
}
/**
Subclasses must override this method and use it to return the width and height of the collection view’s content. These values represent the width and height of all the content, not just the content that is currently visible. The collection view uses this information to configure its own content size to facilitate scrolling.
*/
- (CGSize)collectionViewContentSize {
return self.contentSize;
}
/**
Returns the layout information for the item at the specified index path.
This method updates the layout information as needed before returning the specified attributes. Always use this method to retrieve the layout attributes for items in the collection view. Do not query the layout object directly.
*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
if (indexPath.section == 0) {
attributes.frame = CGRectMake(0, 0, _width_, 44);
} else if (indexPath.section == 1) {
NSInteger row = indexPath.row;
CGFloat margin_x = 5;
CGFloat margin_y = 5;
CGFloat item_w = (_width_ - 4 * margin_x) / 3;
CGFloat item_h = item_w;
CGFloat item_x = margin_x + (item_w + margin_x) * (row % 3);
CGFloat item_y = 44 + 10 + (item_h + margin_y) * (row / 3);
attributes.frame = CGRectMake(item_x, item_y, item_w, item_h);
} else if (indexPath.section == 2) {
UICollectionViewLayoutAttributes *attributesTmp = [[self.itemLayoutInfoArray lastObject] lastObject];
CGFloat item_y = CGRectGetMaxY(attributesTmp.frame) + 44;
attributes.frame = CGRectMake(0, item_y, _width_, 44);
} else if (indexPath.section == 3) {
UICollectionViewLayoutAttributes *attributesTmp = [[self.itemLayoutInfoArray lastObject] lastObject];
CGFloat item_h = 44;
CGFloat item_y = CGRectGetMaxY(attributesTmp.frame) + 10 + item_h * indexPath.row;
attributes.frame = CGRectMake(0, item_y, _width_, item_h);
}
return attributes;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:indexPath.section];
if (elementKind == UICollectionElementKindSectionHeader) {
UICollectionViewLayoutAttributes *header_attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:indexPath];
if (indexPath.section == 2 && numberOfItems > 0) {
header_attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:indexPath];
UICollectionViewLayoutAttributes *attributesTmp = [[self.itemLayoutInfoArray lastObject] lastObject];
CGFloat item_y = CGRectGetMaxY(attributesTmp.frame) + 5;
header_attributes.frame = CGRectMake(0, item_y, _width_, 44);
}
return header_attributes;
} else {
UICollectionViewLayoutAttributes *footer_attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:indexPath];
if (indexPath.section == 3 && numberOfItems > 0) {
footer_attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:indexPath];
UICollectionViewLayoutAttributes *attributesTmp = [[self.itemLayoutInfoArray lastObject] lastObject];
NSInteger num_3 = [self.collectionView numberOfItemsInSection:3];
CGFloat item_h = 44;
CGFloat item_y = CGRectGetMaxY(attributesTmp.frame) + 10 + item_h * num_3;
footer_attributes.frame = CGRectMake(0, item_y, _width_, 95);
}
return footer_attributes;
}
}
/**
return an array layout attributes instances for all the views in the given rect
*/
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray *layoutAttributesArr = [NSMutableArray array];
for (NSMutableArray *array in self.layoutInfoArray) {
for (UICollectionViewLayoutAttributes *attributes in array) {
[layoutAttributesArr addObject:attributes];
}
}
return layoutAttributesArr;
}
@end
不定期更新 不合適的地方 還請指點~ 感激不盡
相關文章
- android自定義view(自定義數字鍵盤)AndroidView
- netty自定義Decoder用於自定義協議Netty協議
- 自定義VIEWView
- 自定義SnackBar
- 自定義_ajax
- 自定義 Anaconda
- 自定義ClassLoader
- 自定義QTimeEditQT
- 自定義 tabBartabBar
- tailwind自定義AI
- 自定義 GitGit
- 自定義元件元件
- 自定義表格
- 自定義LinkedList
- 自定義useState
- vue自定義全域性元件(或自定義外掛)Vue元件
- 4. 自定義控制元件(4) --- 自定義屬性控制元件
- Android 自定義View:深入理解自定義屬性(七)AndroidView
- MySQL自定義排序MySql排序
- JavaScript自定義事件JavaScript事件
- Maven 自定義archeTypeMaven
- SpringBoot 自定義 starterSpring Boot
- 自定義的PopupWindow
- 自定義元件——TitleView元件View
- 自定義目錄
- 自定義 Artisan 命令
- 自定義型別型別
- Gradle 自定義 pluginGradlePlugin
- 自定義Spring ShellSpring
- 自定義JSON名JSON
- phpstudy自定義版本PHP
- Swift 自定義 UIDatePickerSwiftUI
- 自定義ORM框架ORM框架
- Python自定義排序Python排序
- 自定義 Word 模板
- 自定義圓環
- SpringBoot自定義StarterSpring Boot
- 自定義註解
- uniapp 自定義 pickerAPP