Sagit.Framework For IOS 自动布局教程:15、UITableView、UITableViewCell、UICollectionView、UICollectionViewCell特殊用法介绍 [2021-11-12更新]
前言:
框架对于UITableView、UITableViewCell 封装了不少功能,下面开始介绍。
1、UITableView 基本定义。
@interface UITableView(ST) #pragma mark 核心扩展 typedef void(^OnAddTableCell)(UITableViewCell *cell,NSIndexPath *indexPath); typedef BOOL(^OnDelTableCell)(UITableViewCell *cell,NSIndexPath *indexPath); typedef void(^OnAddTableCellAction)(STUITableViewCellAction *cellAction, NSIndexPath *indexPath); typedef void(^OnAddTableSectionHeaderView)(UIView *sectionHeaderView,NSInteger section);
typedef void(^OnAddTableSectionFooterView)(UIView *sectionFooterView,NSInteger section);
typedef void(^OnAfterTableReloadData)(UITableView *tableView);
//!用于为Table追加每一行的Cell @property (nonatomic,copy) OnAddTableCell addCell; //!用于为Table追加每一行的Cell的滑动菜单 @property (nonatomic,copy) OnAddTableCellAction addCellAction; //!用于为Table追加每一组Section的标题View @property (nonatomic,copy) OnAddTableSectionHeaderView addSectionHeaderView;
//!用于为Table追加每一组Section的Bottom View
@property (nonatomic,copy) OnAddTableSectionFooterView addSectionFooterView;
//!用于为Table移除行的Cell @property (nonatomic,copy) OnDelTableCell delCell; //!用于为Table reloadData 加载完数据后触发 @property (nonatomic,copy) OnAfterTableReloadData afterReload; //!获取Table的数据源 @property (nonatomic,strong) NSMutableArray<id> *source; //!设置Table的数据源 -(UITableView*)source:(NSMutableArray<id> *)dataSource; //!存档所有Cell的高度(由系统控制)[存档格式为:section key,[row Array]] @property (readonly,nonatomic,retain) NSMutableDictionary *heightForCells; //!是否重用Cell(默认Yes) -(BOOL)reuseCell; -(BOOL)reuseCell:(BOOL)yesNo; //!是否自动控制Table的高度 -(BOOL)autoHeight; //!设置是否自动控制Table的高度 -(UITableView*)autoHeight:(BOOL)yesNo; //!获取默认的UITableViewCellStyle -(UITableViewCellStyle)cellStyle; //!设置默认的UITableViewCellStyle -(UITableView*)cellStyle:(UITableViewCellStyle)style; //!获取是否允许编辑【删除】属性 -(BOOL)allowEdit; //!设置是否允许编辑【删除】 -(UITableView*)allowEdit:(BOOL)yesNo; //!移除数据源和数据行(并重新计算且刷新高度) -(UITableView*)afterDelCell:(NSIndexPath*)indexPath; #pragma mark 扩展属性 -(UITableView*)scrollEnabled:(BOOL)yesNo; //!分组数(默认1) -(UITableView*)sectionCount:(NSInteger)count; //!每个Section的num数:参数可以传递:@[@"1",@"2",@"2",@"1"] 或者:@"1,2,2,1" -(UITableView*)rowCountInSections:(id)nums; @end
2、UITableViewCell 基本定义:
@interface UITableViewCell(ST) //!获取当前所在的table,(weak,不能造成双strong引用) @property (readonly,nonatomic,weak) UITableView *table; //!获取Cell的数据源 @property (nonatomic,strong) id source; //!Cell是否重用的Cell,如果是,就不要再添加子控制,避免重复添加。 //@property (readonly,nonatomic,assign) BOOL isReused; //!设置Cell的数据源 -(UITableViewCell *)source:(id)dataSource; //!创建或复用Cell + (instancetype)reuseCell:(UITableView *)tableView index:(NSIndexPath *)index; //!获取Cell所在的行数 -(NSIndexPath*)indexPath; -(UITableViewCell*)indexPath:(NSIndexPath*)indexPath; //!获取是否允许删除属性 -(BOOL)allowDelete; //!设置是否允许删除 -(UITableView*)allowDelete:(BOOL)yesNo; //!数据源中的第一个字段,系统自动设置 -(NSString*)firstValue; -(UITableViewCell*)firstValue:(NSString*)value; //当Cell的高度在绑定后,需要动态根据子内容高度变化,再次刷新高度时使用。 -(UITableViewCell*)resetHeightCache; #pragma mark 扩展属性 -(UITableViewCell*)accessoryType:(UITableViewCellAccessoryType)type; -(UITableViewCell*)selectionStyle:(UITableViewCellSelectionStyle)style;
#pragma mark 扩展
//!获取Cell的滑动菜单项。
@property (nonatomic,strong) STUITableViewCellAction *action;
@end
UITableView 基本用法示例一:
[[[[[sagit addTableView:nil] autoHeight:YES] width:610] toCenter] block:^(UITableView* table) { [table relate:TopBottom v:60 v2:60]; [table backgroundColor:ColorClear]; table.backgroundView=[[[[UIImageView new] image:@"answer_bg_rank"]stretch] width:1 height:1]; table.separatorColor = [ColorWhite alpha:0.2]; table.separatorInset=UIEdgeInsetsMake(0,26, 0, 26); table.addCell = ^(UITableViewCell *cell, NSIndexPath *indexPath) { [cell width:1 height:140]; // 1 代表 100% <=1 被处理成百分比。 cell.accessoryType=UITableViewCellAccessoryNone; cell.backgroundColor=ColorClear; //数据 AnswerUserRankModel *model=[[AnswerUserRankModel new] initWithObject:cell.source]; NSString *score=[[@(model.Score) stringValue] append:@" 分"]; [cell.contentView block:^(UIView* view) { [view width:1 height:1]; if(indexPath.row!=table.source.count-1) { [[[[view addLine:nil color:@"#81F0D7"] width:2 height:30]y:140-15] relate:Right v:26]; [[[[view addLine:nil color:@"#81F0D7"] width:30 height:2] y:140] relate:Right v:26]; } [view addLabel:nil text:STNumString(model.Rank) font:30 color:ColorWhite]; [[STLastView x:50] toCenter:Y]; [[[[view addImageView:nil] url:model.PhotoPath] width:80 height:80] corner:YES]; [[STLastView x:122] toCenter:Y]; [[[[view addLabel:nil text:model.NickName font:30 color:@"#FB8107"] onRight:STPreView x:42] toCenter:Y] width:72*2]; [[[view addImageView:nil img:@"answer_bg_rankscore"] width:196 height:20] block:^(UIImageView* scoreView) { [[scoreView x:192*2] toCenter:Y]; //[[scoreView relate:Right v:160] toCenter:Y]; [[scoreView addLabel:nil text:score font:30 color:@"#81F0D7"] toCenter]; //[scoreView stSizeToFit]; }]; [view onClick:^(id view) { [self stPush:[STNew(@"User") key:@"uid" value:model.UserID]]; }]; }]; }; }];
效果:
UITableView 基本用法示例二:
[[[[sagit addTableView:@"tableView" style:UITableViewStyleGrouped] autoHeight:YES] onBottom:STPreView y:20] block:nil on:^(UITableView* table) { [table reuseCell:NO]; table.addCell = ^(UITableViewCell *cell, NSIndexPath *indexPath) { NSString *name=cell.source[@"name"]; NSString *title=cell.source[@"title"]; NSString *holder=cell.source[@"holder"]; if(holder==nil){holder=title;} NSString *pick=cell.source[@"pick"]; NSString *maxLength=cell.source[@"maxLength"]; [[[cell.contentView addLabel:nil text:title font:30] relate:Left v:50] toCenter:Y];//label是固定的。 UIView *textView; if([title isEqualToString:@"简介"]) { textView=[[[[[cell.contentView addTextView:name placeholder:holder font:30] maxRow:3] maxLength:100] textAlignment:NSTextAlignmentLeft] height:0.8]; UIEdgeInsets inset=textView.asTextView.textContainerInset; inset.left-=5; textView.asTextView.textContainerInset=inset; } else { textView=[[cell.contentView addTextField:name placeholder:holder font:30] height:0.8]; if(maxLength!=nil) { [STLastTextField maxLength:[maxLength integerValue]]; } } [[[textView onRight:STPreView x:50] relate:Right v:0] toCenter:Y]; if(pick==nil) { cell.accessoryType=UITableViewCellAccessoryNone; } else { [[STLastView addClick:@"pick"] key:@"pick" value:pick]; } }; table.afterReload = ^(UITableView *tableView) { if(!self.hasLoaded) { self.hasLoaded=YES; [self setToAll:Sagit.Global.User.user]; } }; }];
效果:
数据源设置:
-(void)initData { [super initData];//加载子UI的数据。 UITableView *table=STFirstTable; table.source=@[@{@"title":@"姓名",@"name":@"NickName",@"maxLength":@"15"}, @{@"title":@"简介",@"name":@"Description",@"holder":@"请简单介绍一下自己!"}, @{@"title":@"公司",@"name":@"Company",@"holder":@"所在公司!",@"maxLength":@"20"}, @{@"title":@"年龄",@"name":@"Age",@"pick":@"年龄"}, @{@"title":@"学历",@"name":@"Edu",@"pick":@"学历"}, @{@"title":@"身高",@"name":@"Height",@"pick":@"身高"}, @{@"title":@"星座",@"name":@"Constellation",@"pick":@"星座"}, @{@"title":@"婚姻",@"name":@"MarrStatus",@"pick":@"婚姻"}, @{@"title":@"职业",@"name":@"Profession",@"pick":@"职业"}, @{@"title":@"收入",@"name":@"Wages",@"pick":@"月薪"}]; [[table sectionCount:2] rowCountInSections:@"3,7"]; //table.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,1, 0.01f)]; table.sectionFooterHeight=0.2; // table.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,1, 1.0f)]; //self.automaticallyAdjustsScrollViewInsets = NO; [table reloadData]; }
UITableView 基本用法示例三:循环嵌套[2021-11-11更新]
-(void)initUI { [[[[sagit addTableView:nil]relate:TopBottom v:100 v2:200] backgroundColor:ColorRed] block:^(UITableView* table) { table.addCell = ^(UITableViewCell *cell, NSIndexPath *indexPath) { [cell backgroundColor:ColorGreen]; [[cell addLabel:nil text:cell.firstValue] toCenter]; [[[cell addSwitch:nil on:NO] onSwitch:^(UISwitch *view) { if(view.on) { [self addTable:cell]; } else { [cell.lastSubView removeFromSuperview]; [cell refleshTableHeight]; } }] relate:Right v:50]; }; table.source=@[@{@"a":@"aa"},@{@"a":@"bb"},@{@"a":@"cc"}]; }]; } -(void)addTable:(UITableViewCell*)cell { [[[[cell addTableView:nil] autoHeight:YES] backgroundColor:ColorBlack] block:^(UITableView* cellTable) { [[cellTable onBottom:cell.lastSubView.preView] x:0]; cellTable.addCell = ^(UITableViewCell *childCell, NSIndexPath *indexPath) { childCell.accessoryType=UITableViewCellAccessoryNone; [[childCell backgroundColor:ColorRandom] width:1 height:100]; NSString * value=childCell.firstValue; [[childCell addLabel:nil text:value] toCenter]; }; cellTable.afterReload = ^(UITableView *tableView) { [cell refleshTableHeight]; }; cellTable.source=@[@{@"b":@"aaaa"},@{@"b":@"bb"},@{@"b":@"cc"}]; }]; }
代码细节说明:
Table循环嵌套时,由于表格加载,有延后时,所以,需要在子表格的afterReolad事件(即加载完后)处理。
单元格新增了:refleshTableHeight:刷新表格高度。该方法仅会刷新单元格和表格的高度(不触发table的reload事件)。
循环效果图:
UICollectionView、UICollectionViewCell 基本定义
@interface UICollectionView(ST) #pragma mark 核心扩展 typedef void(^AddCollectionCell)(UICollectionViewCell *cell,NSIndexPath *indexPath); typedef BOOL(^DelCollectionCell)(UICollectionViewCell *cell,NSIndexPath *indexPath); //!用于为Table追加每一行的Cell @property (nonatomic,copy) AddCollectionCell addCell; //!用于为Table移除行的Cell @property (nonatomic,copy) DelCollectionCell delCell; //!获取Table的数据源 @property (nonatomic,strong) NSMutableArray<id> *source; //!设置Table的数据源 -(UITableView*)source:(NSMutableArray<id> *)dataSource; @end
---------------------------------------------
@interface UICollectionViewCell(ST) //!获取Cell的数据源 @property (nonatomic,strong) NSMutableDictionary<NSString*,id> *source; //!设置Cell的数据源 -(UICollectionViewCell *)source:(NSMutableDictionary<NSString*,id> *)dataSource; //!创建或复用Cell + (instancetype)reuseCell:(UICollectionView *)tableView index:(NSIndexPath *)index; //!获取当前所在的table -(UICollectionView*)table; //!获取是否允许删除属性 //-(BOOL)allowDelete; //!设置是否允许删除 //-(UITableView*)allowDelete:(BOOL)yesNo; //!数据源中的第一个字段,系统自动设置 -(NSString*)firstValue; -(UICollectionViewCell*)firstValue:(NSString*)value; @end
这两个和上面两个的用法基本一致,功能比上面的还少,就不过多介绍了。
3、左滑菜单说明
如果左滑的菜单只有删除,那么只需要设置:
[table allowEdit:YES]
删除点击的事件:
table.delCell = ^BOOL(UITableViewCell *cell, NSIndexPath *indexPath) { [Sagit.RongYun removeFromBlacklist:cell.firstValue success:^{ [this.http get:UrlSetBlacklist paras:@{@"blackUserID":cell.firstValue, @"blackFlag":@"2"} success:^(STHttpModel *result) { if (result.success) { [cell.table afterDelCell:indexPath]; } } ]; } error:^(RCErrorCode status) { }]; return false; };
默认是处理完业务,return true;(之后框架会调用 afterDelCell 移除行并重绘高度)。
如果有异步操作,也可以先return false; 再根据结果自己调用 afterDelCell 方法。
如果涉及到添加多个菜单:
原生事件:
-(NSArray<UITableViewRowAction*>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { RCConversationModel *model = self.conversationListDataSource[indexPath.row]; UITableViewRowAction *del = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"删除" handler:^(UITableViewRowAction * _Nonnull action,NSIndexPath * _Nonnull indexPath) { ...... }]; UITableViewRowAction *top = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"置顶" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { ...... }]; top.backgroundColor = STColor(@"#fe9d00"); return @[del, top]; }
框架用法 [2020-09-17更新]
table.addCellAction = ^(STUITableViewCellAction *actions, NSIndexPath *indexPath) { [actions addAction:@"置顶" bgColor:ColorRed onAction:nil]; [actions addAction:@"删除2" bgColor:ColorBlack onAction:^(UITableViewCell *cell, NSIndexPath *indexPath) { //点击事件。 }]; };
结果图:
如果需要自定义滑动菜单:
【原生的方法:可以改变样式,但改变不了坐标,所以在原生的基础上添加自己的视图即可】
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell=[tableView cellForRowAtIndexPath:indexPath]; if(cell!=nil) { UIView *uiSwipeActionPullView=cell.superview.subviews[0]; //UISwipeActionPullView if([uiSwipeActionPullView isKindOfClass:[UITableViewCell class]]) { //IOS 13 以下。 for (UIView *view in tableView.subviews) { if([view isKindOfClass:NSClassFromString(@"UISwipeActionPullView")]) { uiSwipeActionPullView=view; break; } } } //uiSwipeActionPullView=>UISwipeActionStandardButton => UIView,UIButtonLabel for (UIView * btnView in uiSwipeActionPullView.subviews) { [btnView backgroundColor:STDeviceColor]; [btnView removeAllSubViews]; [[[[[[btnView addButton:nil title:@"click" font:24 color:ColorGreen img:nil] width:120 height:0.8] layerCornerRadius:24] toCenter:Y] backgroundColor:ColorBlue] x:20]; } } }
滑动后的布级层级:(IOS 13) 【IOS13以下的View层级是在UITableView下】
框架用法 [2020-09-17更新]
table.addCellAction = ^(STUITableViewCellAction *actions, NSIndexPath *indexPath) { [actions addAction:^(UIView *cellSwipeView, NSIndexPath *indexPath) { [[[[[[cellSwipeView addButton:nil title:@"click" font:24 color:ColorGreen img:nil] width:120 height:0.8] layerCornerRadius:24] toCenter:Y] backgroundColor:ColorBlue] x:20]; } onAction:nil]; };
效果图:
PS:addAction 有两个重载方法,一个用于原生的文字和背景色调整;另一个用于自定样式。
4、分区标题
原生用法:
// 设置表头的高度。如果使用自定义表头,该方法必须要实现,否则自定义表头无法执行,也不会报错 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 80*Ypt; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UIView *view=[[[UIView new] width:1 height:80] backgroundColor:[ColorBlue alpha:0.5]]; [[[view addLabel:nil text:@"title"] toCenter] sizeToFit]; [[view stSizeToFit] layerCornerRadius:20 byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight]; return view; }
框架用法: [2021-11-11更新]
table.addSectionHeaderView = ^(UIView *sectionView, NSInteger section) { [sectionView backgroundColor:[ColorBlue alpha:0.5]]; [[[sectionView addLabel:nil text:@"title"] toCenter] sizeToFit]; [[sectionView stSizeToFit] layerCornerRadius:20 byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight]; };
结果图片:
相关文章
暂无评论...