UITableView
概念
举个不恰当的例子:
火车头 车厢头-座-车厢尾 车厢头-座-座-车厢尾 火车尾
火车头:tableHeaderView
火车尾:tableFooterView
车厢头:sectionHeader
车厢尾:sectionFooter
座:cell
使用步骤
1.创建tableView 设置dele/dataSource,注册cell
2.创建自定义CELL(初始化控件---UI,一个对外方法---写入数据)
3.cellForRow中dequ使用(不用再判断为nil的情况) ,行数/组数根据数据源数组来确定
4.
cell高度可变
Model中加个height属性
// 行
[NSIndexPath indexPathForRow:0 inSection:0];
// 组
[NSIndexSet indexSetWithIndex:0];
复用原理
UITableView有2个数组(可视数组 和 复用数组)。当需要显示Cell时,先从复用数组中查找,如果有则复用,如果没有则创建并加入到可视数组中。当cell不再需要显示时,将cell从可视数组中移除,并放入复用数组。通过不同的identify标示符来复用不同类型的Cell。
一个tableView只能有一个数据源,一个Controller可以有多个tableView,通过tag进行区分
-(void)registerClass{
[self.tableView registerClass:[YTBaseTableViewCell class] forCellReuseIdentifier:NSStringFromClass([YTBaseTableViewCell class])];
}
// 懒加载
-(NSMutableArray *)dataSourceArr{
if(!_dataSourceArr){
_dataSourceArr =[NSMutableArray new];
}
return _dataSourceArr;
}
-(UITableView *)tableView{
if(!_tableView){
// plain:头视图会有悬停,grouped:无悬停效果
_tableView=[[UITableView alloc]initWithFrame:CGRectMake(0, YTNavbarHeight, YTScreen_Width, YTScreen_Height-YTNavbarHeight-YTTabBarHeight) style:UITableViewStylePlain];
[_tableView setDelegate:self];
[_tableView setDataSource:self];
[_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone]; // 分割线style
[_tableView setShowsVerticalScrollIndicator:false];
[_tableView setBackgroundColor:[UIColor whiteColor]];
[self registerClass];
}
return _tableView;
}
UITableView的常用方法
// 禁止编辑
[_tableView setEditing:false];
[_tableView setEditing:false animated:true];
// 分割线的颜色
[_tableView setSeparatorColor:[UIColor blackColor]];
// tableView头/尾视图 高
[_tableView setTableHeaderView:[UIView new]];
[_tableView setTableFooterView:[UIView new]];
[_tableView setSectionFooterHeight:10];
[_tableView setSectionHeaderHeight:10];
// cell高,预估行高
[_tableView setRowHeight:44];
[_tableView setEstimatedRowHeight:55];
// bgView
[_tableView setBackgroundView:[UIView new]];
// 刷新UI
[_tableView reloadData];
// 刷新索引
[_tableView reloadSectionIndexTitles];
// 刷新某组
[_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
// 刷新某行
[_tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
// 滚动到指定行
[_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:true];
// 滚动到最近被选中的cell
[_tableView scrollToNearestSelectedRowAtScrollPosition:UITableViewScrollPositionTop animated:true];
// 替换某组和某组
[_tableView moveSection:0 toSection:1];
// 替换某行和某行
[_tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] toIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]];
// 删除某组
[_tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationTop];
// 删除某行
[_tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
// 插入一组
[_tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationTop];
// 插入一行
[_tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
// 选中某行
[_tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:true scrollPosition:UITableViewScrollPositionTop];
// 反选中某行
[_tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:true];
// 选中cell的indexPath
NSIndexPath *indexPath=_tableView.indexPathForSelectedRow;
// 选中cell的indexPath数组
NSArray<NSIndexPath *> *selectsArr=_tableView.indexPathsForSelectedRows;
// 可视cell的indexPath数组
NSArray<NSIndexPath *> *visibleArr=_tableView.indexPathsForVisibleRows;
// 通过indexPath获取cell
UITableViewCell *cell=[_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
// 是否允许选中
[_tableView setAllowsSelection:true];
// 是否允许多选
[_tableView setAllowsMultipleSelection:true];
// 编辑时是否允许选中
[_tableView setAllowsSelectionDuringEditing:true];
// 编辑时允许多选
[_tableView setAllowsMultipleSelectionDuringEditing:true];
// 注册cell,头尾视图
[_tableView registerNib:[UINib nibWithNibName:@"xibName" bundle:nil] forCellReuseIdentifier:@"iden"];
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:NSStringFromClass([UITableViewCell class])];
[_tableView registerClass:[UIView class] forHeaderFooterViewReuseIdentifier:NSStringFromClass([UIView class])];
[_tableView registerNib:[UINib nibWithNibName:@"xibName" bundle:nil] forHeaderFooterViewReuseIdentifier:@"iden"];
UITableView代理方法
常用
// 组数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
// 行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.dataSourceArr.count;
}
// 行高
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
// 每行
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
YTBaseTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([YTBaseTableViewCell class])];
return cell;
}
// didSelect
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}
// 头视图/尾视图 height
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return CGFLOAT_MIN;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
return CGFLOAT_MIN;
}
// 头视图/尾视图 View
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
return [UIView new];
}
-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
return [UIView new];
}
或者
// 头视图/尾视图 标题
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
return @"head";
}
-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{
return @"foot";
}
选中
// 反选一行时调用(选择一行后再次选择该行)
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{}
// 即将选中/即将反选 一行时调用
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{
return nil; // 不允许选
return indexPath; // 默认,允许选
}
-(NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath{}
编辑(删除/插入)
// 是否允许编辑
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return true;
}
// 返回每行的编辑style
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert;
}
// 编辑时调用
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if(editingStyle==UITableViewCellEditingStyleDelete){}
}
// 将要编辑时调用
-(void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath{}
// 结束编辑时调用
-(void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath{}
// 编辑时每行是否缩进
-(BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{
return true;
}
// 返回每行缩进
-(NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath{
return 100;
}
// 左滑出现的删除 标题
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{
return @"";
}
// 左滑 自定义右侧按钮
-(NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
return @[[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
}],[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"好的" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
}]];
}
长按
// 返回 长按每行时 是否显示Menu菜单
-(BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath{
return true;
}
// 返回 长按每行出现的菜单选项
-(BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender{
if(action==@selector(cut:)){
return true;
}
return false;
}
// 点击菜单某项后调用
-(void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender{
if(action==@selector(cut:)){
[UIPasteboard generalPasteboard].string=@"";
}
}
移动
// 是否允许移动
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{
return true;
}
// 移动过程中会多次调用 (下述操作:限制只能在本section中移动)
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{
// 原有indexPath:sourceIndexPath
// 目标indexPath:proposedDestinationIndexPath
if(proposedDestinationIndexPath.section!=sourceIndexPath.section){
return sourceIndexPath;
}
return proposedDestinationIndexPath;
}
// 移动结束后调用
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
// 修改数据源(先删除再插入 根据index)
}
索引
// 返回 索引标题数组
-(NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView{
return @[@"1"];
}
// 返回 索引 (下列操作:加了search图标后) (点击索引标题后调用 ,跳到相应section)
-(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index{
if(index==0){
tableView.contentOffset=CGPointZero;
}
return index-1;
}
即将 显示/结束显示,估算高度
// 即将显示 头视图/尾视图/cell 时调用
-(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section{}
-(void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section{}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{}
// 即将结束显示 头视图/尾视图/cell 时调用
-(void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section{}
-(void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section{}
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{}
// 估算 头视图/尾视图/cell 高度
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section{
return CGFLOAT_MIN;
}
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section{
return CGFLOAT_MIN;
}
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
其他
// 点击cell右侧图标时调用
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{}
// 是否允许高亮
-(BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath{
return true;
}
// 高亮时调用
-(void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath{}
// 反高亮时调用
-(void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath{}
系统CELL
基本不用
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"iden"];
if(!cell){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"iden"];
}
style
UITableViewCellStyleDefault, // 从左到右(imageView(可选)->textLabel
UITableViewCellStyleValue1, // 从左到右(imageView(可选)->textLabel(粗黑)->detailTextLabel(右侧、蓝)
UITableViewCellStyleValue2, // 从左到右(imageView(可选)->textLabel(蓝)->detailTextLabel(紧跟textLabel)
UITableViewCellStyleSubtitle // 从左到右(imageView(可选)->textLabel(上方、粗黑),detailTextLabel(下方、灰色)
cell.textLabel
cell.imageView
cell.detailTextLabel
cell常用方法
// 自定义右侧View
[cell setAccessoryView:[UIView new]];
// cell右侧图标
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
图标style
UITableViewCellAccessoryNone 无
UITableViewCellAccessoryDisclosureIndicator >
UITableViewCellAccessoryDetailDisclosureButton ?>
UITableViewCellAccessoryCheckmark 对勾
UITableViewCellAccessoryDetailButton 信息按钮
// 分割线距屏幕两边为0(默认左方有间隙)
[cell setSeparatorInset:UIEdgeInsetsZero];
[cell setLayoutMargins:UIEdgeInsetsZero];
// 设置选中后不变灰
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
SelectionStyle
UITableViewCellSelectionStyleNone // 无
UITableViewCellSelectionStyleBlue // 变蓝
UITableViewCellSelectionStyleGray // 变灰
自定义CELL
registerClass在VC中实现
Cell.h
@interface Cell : UITableViewCell
-(void)cellWithIndexPath:(NSIndexPath *)indexPath withModel:(YTCupSetViewModel *)model;
@end
Cell.m
@interface Cell()
各种控件 与 约束
@property (nonatomic,weak) UIView *headView;
@property (nonatomic,strong) NSLayoutConstraint *headC;
@end
@implementation Cell
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
self.selectionStyle=UITableViewCellSelectionStyleNone;
// UI
[self setupUI];
}
return self;
}
-(void)setupUI{
}
-(void)cellWithIndexPath:(NSIndexPath *)indexPath withModel:(YTModel *)model{
给各种控件赋值
删除并新建约束
}
// 通过xib创建的cell
- (void)awakeFromNib {
[super awakeFromNib];
[self setupUI];
}
@end
registerClass在cell中实现(基本不用)
Cell.h
+(instancetype)CreateWithTableView:(UITableView *)tableView;
Cell.m
// 代码实现
+(instancetype)CreateWithTableView:(UITableView *)tableView{
YTPlaceTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([YTPlaceTableViewCell class])];
if(!cell){
cell=[[YTPlaceTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass([YTPlaceTableViewCell class])];
}
return cell;
}
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
self.selectionStyle=UITableViewCellSelectionStyleNone;
// UI
[self setupUI];
}
return self;
}
//
-(void)setupUI{
}
网友评论