项目文件夹

文件
2026-07-13 12:35:01 +08:00

468 行
16 KiB
Objective-C

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
//
// ZZFlexibleLayoutViewController.m
// zhuanzhuan
//
// Created by 李伯坤 on 2016/10/10.
// Copyright © 2016年 wuba. All rights reserved.
//
#import "ZZFlexibleLayoutViewController.h"
#import "ZZFlexibleLayoutViewController+Kernel.h"
#import "ZZFlexibleLayoutViewController+OldAPI.h"
#import "ZZFlexibleLayoutSectionModel.h"
#import "ZZFlexibleLayoutViewProtocol.h"
#import "ZZFlexibleLayoutSeperatorCell.h"
#import "ZZFLEXMacros.h"
@implementation ZZFlexibleLayoutViewController
- (id)init
{
if (self = [super init]) {
_data = [[NSMutableArray alloc] init];
_scrollDirection = UICollectionViewScrollDirectionVertical;
ZZFlexibleLayoutFlowLayout *layout = [[ZZFlexibleLayoutFlowLayout alloc] init];
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
[self.collectionView setBackgroundColor:[UIColor clearColor]];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
[self.collectionView setShowsHorizontalScrollIndicator:NO];
[self.collectionView setAlwaysBounceVertical:YES];
}
return self;
}
- (void)loadView
{
[super loadView];
[self.view addSubview:self.collectionView];
RegisterCollectionViewCell(self.collectionView, CELL_SEPEARTOR); // 注册空白cell
RegisterCollectionViewReusableView(self.collectionView, UICollectionElementKindSectionHeader, @"ZZFlexibleLayoutEmptyHeaderFooterView");
RegisterCollectionViewReusableView(self.collectionView, UICollectionElementKindSectionFooter, @"ZZFlexibleLayoutEmptyHeaderFooterView");
}
- (void)dealloc
{
ZZFLEXLog(@"Dealloc: %@", NSStringFromClass([self class]));
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
if (!CGRectEqualToRect(self.view.bounds, self.collectionView.frame)) {
[self.collectionView setFrame:self.view.bounds];
self.updateCells.all();
[self reloadView];
}
}
#pragma mark - # API
- (void)setScrollDirection:(UICollectionViewScrollDirection)scrollDirection
{
_scrollDirection = scrollDirection;
[(ZZFlexibleLayoutFlowLayout *)self.collectionView.collectionViewLayout setScrollDirection:scrollDirection];
}
#pragma mark 页面刷新
/// 刷新页面
- (void)reloadView
{
[UIView performWithoutAnimation:^{
[self.collectionView reloadData];
}];
}
#pragma mark - # 整体
- (BOOL (^)(void))clear
{
@weakify(self);
return ^(void) {
@strongify(self);
[self.data removeAllObjects];
return YES;
};
}
- (BOOL (^)(void))clearAllCells
{
@weakify(self);
return ^(void) {
@strongify(self);
for (ZZFlexibleLayoutSectionModel *sectionModel in self.data) {
[sectionModel.itemsArray removeAllObjects];
}
return YES;
};
}
/// 更新所有元素
- (BOOL (^)(void))upadte
{
@weakify(self);
return ^(void) {
@strongify(self);
for (ZZFlexibleLayoutSectionModel *sectionModel in self.data) {
[sectionModel.headerViewModel updateViewHeight];
[sectionModel.footerViewModel updateViewHeight];
for (ZZFlexibleLayoutViewModel *viewModel in sectionModel.itemsArray) {
[viewModel updateViewHeight];
}
}
return YES;
};
}
/// 更新所有Cell
- (BOOL (^)(void))upadteAllCells
{
@weakify(self);
return ^(void) {
@strongify(self);
for (ZZFlexibleLayoutSectionModel *sectionModel in self.data) {
for (ZZFlexibleLayoutViewModel *viewModel in sectionModel.itemsArray) {
[viewModel updateViewHeight];
}
}
return YES;
};
}
#pragma mark - # Section操作
/// 添加section
- (ZZFLEXChainSectionModel *(^)(NSInteger tag))addSection
{
@weakify(self);
return ^(NSInteger tag){
@strongify(self);
if (self.hasSection(tag)) {
ZZFLEXLog(@"!!!!! 重复添加Section%ld", (long)tag);
}
ZZFlexibleLayoutSectionModel *sectionModel = [[ZZFlexibleLayoutSectionModel alloc] init];
sectionModel.sectionTag = tag;
[self.data addObject:sectionModel];
ZZFLEXChainSectionModel *chainSectionModel = [[ZZFLEXChainSectionModel alloc] initWithSectionModel:sectionModel];
return chainSectionModel;
};
}
- (ZZFLEXChainSectionInsertModel *(^)(NSInteger tag))insertSection
{
@weakify(self);
return ^(NSInteger tag){
@strongify(self);
if (self.hasSection(tag)) {
ZZFLEXLog(@"!!!!! 重复添加Section%ld", (long)tag);
}
ZZFlexibleLayoutSectionModel *sectionModel = [[ZZFlexibleLayoutSectionModel alloc] init];
sectionModel.sectionTag = tag;
ZZFLEXChainSectionInsertModel *chainSectionModel = [[ZZFLEXChainSectionInsertModel alloc] initWithSectionModel:sectionModel listData:self.data];
return chainSectionModel;
};
}
/// 获取section
- (ZZFLEXChainSectionEditModel *(^)(NSInteger tag))sectionForTag
{
@weakify(self);
return ^(NSInteger tag){
@strongify(self);
ZZFlexibleLayoutSectionModel *sectionModel = nil;
for (sectionModel in self.data) {
if (sectionModel.sectionTag == tag) {
ZZFLEXChainSectionEditModel *chainSectionModel = [[ZZFLEXChainSectionEditModel alloc] initWithSectionModel:sectionModel];
return chainSectionModel;
}
}
return [[ZZFLEXChainSectionEditModel alloc] initWithSectionModel:nil];
};
}
/// 删除section
- (BOOL (^)(NSInteger tag))deleteSection
{
@weakify(self);
return ^(NSInteger tag) {
@strongify(self);
ZZFlexibleLayoutSectionModel *sectionModel = [self sectionModelForTag:tag];
if (sectionModel) {
[self.data removeObject:sectionModel];
return YES;
}
return NO;
};
}
/// 判断section是否存在
- (BOOL (^)(NSInteger tag))hasSection
{
@weakify(self);
return ^(NSInteger tag) {
@strongify(self);
BOOL hasSection = [self sectionModelForTag:tag] ? YES : NO;
return hasSection;
};
}
- (NSInteger)sectionIndexForTag:(NSInteger)sectionTag
{
for (int section = 0; section < self.data.count; section++) {
ZZFlexibleLayoutSectionModel *sectionModel = self.data[section];
if (sectionModel.sectionTag == sectionTag) {
return section;
}
}
return 0;
}
- (BOOL)deleteAllItemsForSection:(NSInteger)tag
{
ZZFlexibleLayoutSectionModel *sectionModel = [self sectionModelForTag:tag];
if (sectionModel) {
sectionModel.headerViewModel = nil;
sectionModel.footerViewModel = nil;
[sectionModel.itemsArray removeAllObjects];
return YES;
}
return NO;
}
- (BOOL)deleteAllCellsForSection:(NSInteger)tag {
ZZFlexibleLayoutSectionModel *sectionModel = [self sectionModelForTag:tag];
if (sectionModel) {
[sectionModel.itemsArray removeAllObjects];
return YES;
}
return NO;
}
#pragma mark - # Section View 操作
//MARK: Header
- (ZZFLEXChainViewModel *(^)(NSString *className))setHeader
{
@weakify(self);
return ^(NSString *className) {
@strongify(self);
ZZFlexibleLayoutViewModel *viewModel;
if (className) {
viewModel = [[ZZFlexibleLayoutViewModel alloc] init];
viewModel.className = className;
}
RegisterCollectionViewReusableView(self.collectionView, UICollectionElementKindSectionHeader, className);
ZZFLEXChainViewModel *chainViewModel = [[ZZFLEXChainViewModel alloc] initWithListData:self.data viewModel:viewModel andType:ZZFLEXChainViewTypeHeader];
return chainViewModel;
};
}
//MARK: Footer
- (ZZFLEXChainViewModel *(^)(NSString *className))setFooter
{
@weakify(self);
return ^(NSString *className) {
@strongify(self);
ZZFlexibleLayoutViewModel *viewModel;
if (className) {
viewModel = [[ZZFlexibleLayoutViewModel alloc] init];
viewModel.className = className;
}
RegisterCollectionViewReusableView(self.collectionView, UICollectionElementKindSectionFooter, className);
ZZFLEXChainViewModel *chainViewModel = [[ZZFLEXChainViewModel alloc] initWithListData:self.data viewModel:viewModel andType:ZZFLEXChainViewTypeFooter];
return chainViewModel;
};
}
#pragma mark - # Cell 操作
/// 添加cell
- (ZZFLEXChainViewModel *(^)(NSString *className))addCell
{
@weakify(self);
return ^(NSString *className) {
@strongify(self);
RegisterCollectionViewCell(self.collectionView, className);
ZZFlexibleLayoutViewModel *viewModel = [[ZZFlexibleLayoutViewModel alloc] init];
viewModel.className = className;
ZZFLEXChainViewModel *chainViewModel = [[ZZFLEXChainViewModel alloc] initWithListData:self.data viewModel:viewModel andType:ZZFLEXChainViewTypeCell];
return chainViewModel;
};
}
/// 批量添加cell
- (ZZFLEXChainViewBatchModel *(^)(NSString *className))addCells
{
@weakify(self);
return ^(NSString *className) {
@strongify(self);
RegisterCollectionViewCell(self.collectionView, className);
ZZFLEXChainViewBatchModel *viewModel = [[ZZFLEXChainViewBatchModel alloc] initWithClassName:className listData:self.data];
return viewModel;
};
}
/// 添加空白cell
- (ZZFLEXChainViewModel *(^)(CGSize size, UIColor *color))addSeperatorCell;
{
@weakify(self);
return ^(CGSize size, UIColor *color) {
@strongify(self);
ZZFlexibleLayoutViewModel *viewModel = [[ZZFlexibleLayoutViewModel alloc] init];
viewModel.className = CELL_SEPEARTOR;
viewModel.dataModel = [[ZZFlexibleLayoutSeperatorModel alloc] initWithSize:size andColor:color];
ZZFLEXChainViewModel *chainViewModel = [[ZZFLEXChainViewModel alloc] initWithListData:self.data viewModel:viewModel andType:ZZFLEXChainViewTypeCell];
return chainViewModel;
};
}
/// 插入cell
- (ZZFLEXChainViewInsertModel *(^)(NSString *className))insertCell
{
@weakify(self);
return ^(NSString *className) {
@strongify(self);
RegisterCollectionViewCell(self.collectionView, className);
ZZFlexibleLayoutViewModel *viewModel = [[ZZFlexibleLayoutViewModel alloc] init];
viewModel.className = className;
ZZFLEXChainViewInsertModel *chainViewModel = [[ZZFLEXChainViewInsertModel alloc] initWithListData:self.data viewModel:viewModel andType:ZZFLEXChainViewTypeCell];
return chainViewModel;
};
}
/// 批量插入cells
- (ZZFLEXChainViewBatchInsertModel *(^)(NSString *className))insertCells
{
@weakify(self);
return ^(NSString *className) {
@strongify(self);
RegisterCollectionViewCell(self.collectionView, className);
ZZFLEXChainViewBatchInsertModel *viewModel = [[ZZFLEXChainViewBatchInsertModel alloc] initWithClassName:className listData:self.data];
return viewModel;
};
}
/// 删除cell
- (ZZFLEXChainViewEditModel *)deleteCell
{
ZZFLEXChainViewEditModel *deleteModel = [[ZZFLEXChainViewEditModel alloc] initWithType:ZZFLEXChainViewEditTypeDelete andListData:self.data];
return deleteModel;
}
/// 批量删除cell
- (ZZFLEXChainViewBatchEditModel *)deleteCells
{
ZZFLEXChainViewBatchEditModel *deleteModel = [[ZZFLEXChainViewBatchEditModel alloc] initWithType:ZZFLEXChainViewEditTypeDelete andListData:self.data];
return deleteModel;
}
/// 更新cell
- (ZZFLEXChainViewEditModel *)updateCell
{
ZZFLEXChainViewEditModel *deleteModel = [[ZZFLEXChainViewEditModel alloc] initWithType:ZZFLEXChainViewEditTypeUpdate andListData:self.data];
return deleteModel;
}
/// 批量更新cell
- (ZZFLEXChainViewBatchEditModel *)updateCells
{
ZZFLEXChainViewBatchEditModel *deleteModel = [[ZZFLEXChainViewBatchEditModel alloc] initWithType:ZZFLEXChainViewEditTypeUpdate andListData:self.data];
return deleteModel;
}
/// 包含cell
- (ZZFLEXChainViewEditModel *)hasCell
{
ZZFLEXChainViewEditModel *deleteModel = [[ZZFLEXChainViewEditModel alloc] initWithType:ZZFLEXChainViewEditTypeHas andListData:self.data];
return deleteModel;
}
#pragma mark - # DataModel 数据源获取
/// 数据源获取
- (ZZFLEXChainViewEditModel *)dataModel
{
ZZFLEXChainViewEditModel *dataModel = [[ZZFLEXChainViewEditModel alloc] initWithType:ZZFLEXChainViewEditTypeDataModel andListData:self.data];
return dataModel;
}
/// 批量获取数据源
- (ZZFLEXChainViewBatchEditModel *)dataModelArray
{
ZZFLEXChainViewBatchEditModel *dataModel = [[ZZFLEXChainViewBatchEditModel alloc] initWithType:ZZFLEXChainViewEditTypeDataModel andListData:self.data];
return dataModel;
}
@end
#pragma mark - ## ZZFlexibleLayoutViewController (View)
@implementation ZZFlexibleLayoutViewController (View)
- (void)scrollToTop:(BOOL)animated
{
[self.collectionView setContentOffset:CGPointZero animated:animated];
}
- (void)scrollToBottom:(BOOL)animated
{
CGFloat y = self.collectionView.contentSize.height - self.collectionView.frame.size.height;
[self.collectionView setContentOffset:CGPointMake(0, y) animated:animated];
}
- (void)scrollToSection:(NSInteger)sectionTag position:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated
{
if (self.hasSection(sectionTag)) {
NSInteger section = [self sectionIndexForTag:sectionTag];
NSUInteger sectionCount = [self.collectionView numberOfSections];
if (sectionCount > section) {
NSUInteger itemCount = [self.collectionView numberOfItemsInSection:section];
if (itemCount > 0) {
NSInteger index = 0;
if (scrollPosition == UICollectionViewScrollPositionBottom || scrollPosition == UICollectionViewScrollPositionRight) {
scrollPosition = itemCount - 1;
}
else if (scrollPosition == UICollectionViewScrollPositionCenteredVertically || scrollPosition == UICollectionViewScrollPositionCenteredHorizontally) {
scrollPosition = itemCount / 2.0;
}
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:section] atScrollPosition:scrollPosition animated:animated];
}
}
}
}
- (void)scrollToSection:(NSInteger)sectionTag cell:(NSInteger)cellTag position:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated
{
NSArray *indexPaths = [self cellIndexPathForSectionTag:sectionTag cellTag:cellTag];
if (indexPaths.count > 0) {
NSIndexPath *indexPath = indexPaths[0];
[self scrollToIndexPath:indexPath position:scrollPosition animated:animated];
}
}
- (void)scrollToCell:(NSInteger)cellTag position:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated
{
NSArray *indexPaths = [self cellIndexPathForCellTag:cellTag];
if (indexPaths.count > 0) {
NSIndexPath *indexPath = indexPaths[0];
[self scrollToIndexPath:indexPath position:scrollPosition animated:animated];
}
}
- (void)scrollToSectionIndex:(NSInteger)sectionIndex position:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated
{
if (sectionIndex < self.data.count) {
[self scrollToIndexPath:[NSIndexPath indexPathForItem:0 inSection:sectionIndex] position:scrollPosition animated:animated];
}
}
- (void)scrollToIndexPath:(NSIndexPath *)indexPath position:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated
{
if (self.hasCell.atIndexPath(indexPath)) {
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated];
}
}
@end