创建TableView(继承于UIScrollView)
1、注意如果是导航控制器,tableView会向下偏移64.
- 形如某个控制器:设为ViewController,那么在他的初始化的时候,要加上self.automaticallyAdjustsScrollViewInsets = NO;(默认值为YES)。这样tableView的高度就会遵循你的分配,不会在刚显示的时候出现下移。
2、常用属性
如:
UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 400) style:UITableViewStyleGrouped]; //高度取决于自己(内部的cell可以排很远,不用担心,后面的样式注意,与后面的section设置应该一致)
tableView.bounds = NO; //(因为继承UITableView)设置拉到头或者尾的时候不能弹性的拉动
tableView.separatorStyle = UITableViewCellSeparatorStyleNone(可设置为无,或者单行等样式) //通过sepatator...提示出来的东西可以设置分割线的颜色,距离边界的位置等等
tableView.allowsSelection = NO; //设置cell是否可选
//tableView.rowHeight = 100; //设置行高,此处可根据后面的函数动态设置方法较好
//设置两个代理......要在当前控制器遵循对应的两个协议 。“并在后面实现代理方法,以进行控制”
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
3、必须要实现的两个方法 (同时含有一种从复用池里面取cell得方法)
#pragma mark
#pragma mark ------------------UITableViewDataSource
//第一个方法
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
//对section进行操作,然后进行判断
return 5;
}
//第二个方法
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifer = @"cellId";
//从cell复用池去cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifer];
if (nil == cell) {
// UITableViewCellStyleDefault,
// UITableViewCellStyleValue1, //imageView textLabel detailTextLabel(同一行显示)
// UITableViewCellStyleValue2, //textLabel detailTextlabel
// UITableViewCellStyleSubtitle //image textLabel detailTextLabel(在textLabel下面)
// 此处不能在 UITableViewCell *cell 否则会蹦
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cellId"];
cell.textLabel.text = [NSString stringWithFormat:@"section:%ld row:%ld",indexPath.section,indexPath.row];
cell.detailTextLabel.text = @"第一个tableDemo";
cell.imageView.image = [UIImage imageNamed:@"26_2.jpg"];
//可以设置背景为自定义背景
UIView *myView = [[UIView alloc]init];
myView.backgroundColor = [UIColor blueColor];
cell.selectedBackgroundView = myView; //这个属性设置背景属性
//设置当前cell被选中时候的样式 (老师说不起什么用作)
//cell.selectionStyle = UITableViewCellSelectionStyleBlue;
//设置右侧的样式
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
//UITableViewCell *cell = [[UITableViewCell alloc]init];
//
// 自定义附件视图,会覆盖上面的有些上面右侧风格(此处可以在myView上搞一些控件啊什么的,达到需求)
// UIView *myView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 30, 30)];
// myView.backgroundColor = [UIColor redColor];
// cell.accessoryView = myView;
return cell;
}
-------------------------
//非必须实现的方法
//设置有个几分组,不写此方法默认为1咯
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 3;
}
#pragma mark
#pragma mark --------------------------UITableViewDelegate
//自定义sectionHeaderView
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection: (NSInteger)section{
UIView * headerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0,CGRectGetWidth(self.view.frame), 30)];
headerView.backgroundColor = [UIColor cyanColor];
if (section != 0) {
return nil;
}
return headerView;
}
//只有调制了sectionHeaderView的高度才可显示。
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
if (section != 0) {
return 0;
}
return 30.0;
}
//自定义footer类似。。。。
//定义一些高度(通过-(CGFloat)tabl...提示出来),此处举例定义row。。。。"如果是自定义cell,此处相当于重写,因为你的自定义要继承父类(UITableViewCell)"
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//获取是那个section;
NSInteger section = indexPath.section;
//获取第几行。
NSInteger row = indexPath.row;
// if (row%2 == 0) {
// return 50.0;
// }
return 200.0;
}
一旦重写cell。上面的高度设置,以及下面一些响应的事件都可以重写,因为继承了父类(UITableViewCell)
//当然还有一些响应方法,具体需要的时候可以查
//当选中cell时会调用的方法。
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"section:%ld row%ld",indexPath.section, indexPath.row);
}
//将要从一个cell的选择状下,去选择另一个cell时会被调用。
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"section:%ld row%ld",indexPath.section, indexPath.row);
}
4、事件响应tableViewEditing
可以先添加俩Button在导航条上(不能够直接添加,要转换,详请见下面),这个个数随意啦
- (void)addButtonItem{
// 正常直接建的barItem
// UIBarButtonItem * barItem = [[UIBarButtonItem alloc]initWithTitle:@"编辑" style:UIBarButtonItemStylePlain target:nil action:nil];
//
// barItem.tintColor = [UIColor whiteColor];
//自定义的button ,通过转换添加在导航条上
UIButton * btn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 40, 30)];
[btn setTitle:@"编辑" forState:UIControlStateNormal];
btn.titleLabel.font = [UIFont systemFontOfSize:20];
[btn addTarget:self action:@selector(editBtn:) forControlEvents:UIControlEventTouchUpInside];
// [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:btn];
}
//通过点击导航栏上的buttonItem,改变cell是否能编辑
- (void)editBtn:(UIButton*)btn{
//static 与程序生命周期一样,故在程序运行且么有退出的过程中,此静态变量只声明一次,就能一直用到程序结束,直到下次重新运行程序在重新创建。
static BOOL state = YES;
if (state) {
[btn setTitle:@"完成" forState:UIControlStateNormal];
[self.tableVeiw setEditing:YES animated:YES];
state = !state;
}else{
[btn setTitle:@"编辑" forState:UIControlStateNormal];
//设置是否可以编辑。
// self.tableVeiw.editing = YES;//没有动画。
//代动画
[self.tableVeiw setEditing:NO animated:YES];
state = !state;
}
}
#pragma mark
#pragma mark ---------------------UITableViewDataSource ---->TableViewEditing
//设置哪些cell(行)可以编辑(默认是全部可以编辑的)
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
//
if (indexPath.section == 0 && indexPath.row == 3) {
return NO;
}
return YES;
}
//设置编辑模式(删除还是插入),可通过按位或设置,如一个特殊的return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert是全选
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row%2 == 0) {
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleInsert;
}
//设置删除时候的文字
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{
return @"删除我啊,长本事了你";
}
*提交编辑,编辑时候触发,并把以下编辑东西,在编辑完成时候提交,故此方法最后要”刷新数据”
//下面在提交编辑方法中实现了删除和添加
//self.models是取好的数据源
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if(editingStyle == UITableViewCellEditingStyleInsert)
//取出改变cell的所属section,准备取出的section,然后更新元数据对应的这个section(先移除,在添加下面取出来改动后的)
NSMutableArray *model = [NSMutableArray arrayWithArray:self.models[indexPath.section]];
NSDictionary *obj = model[indexPath.row];
//假设添加的就为当前行
[model insertObject:obj atIndex:0];
[self.models removeObjectAtIndex:indexPath.section]
[self.models insertObject:model atIndex:indexPath.section];
}
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSMutableArray * model = [NSMutableArray arrayWithArray:self.models[indexPath.section]];
[model removeObjectAtIndex:indexPath.row];
[self.models removeObjectAtIndex:indexPath.section];
[self.models insertObject:model atIndex:indexPath.section];
}
//刷新整个tableView,tableView会把所有加载的方法重新执行一遍,数据会刷新
//[self.tableView reloadData];
//刷新改变的section,此处用这个就可以了。杀鸡焉用宰牛刀
self.tableView reloadSection:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationTop];
}
**移动 用下面两个方法 (区别提交编辑,到最后不用刷新数据,会自动刷新)
//设置可以移动
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
//设置移动里面要干啥
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
//从数据源中取出对应section数组
NSMutableArray * model1 = [NSMutableArray arrayWithArray:self.models[sourceIndexPath.section]];
NSMutableArray * model2 = [NSMutableArray arrayWithArray:self.models[destinationIndexPath.section]];
//要移动的cell对象
id sourceObj = model1[sourceIndexPath.row];
// id destinationObj = model2[destinationIndexPath.row];
//设置section相等情况
if (sourceIndexPath.section == destinationIndexPath.section) {
//移动的时候,相当于是先把元素拿出来,故有下面操作
[model2 removeObjectAtIndex:sourceIndexPath.row];
//对方向进行判定,看添加在其上方还是下方
if (sourceIndexPath.row < destinationIndexPath.row) {
[model2 insertObject:sourceObj atIndex:destinationIndexPath.row-1];
}else{
[model2 insertObject:sourceObj atIndex:destinationIndexPath.row+1];
}
//对源数组更新
[self.models replaceObjectAtIndex:destinationIndexPath.section withObject:model2];
return ;
}
//section不相等,显然要更新两个section
[model2 insertObject:sourceObj atIndex:destinationIndexPath.row];
[model1 removeObjectAtIndex:sourceIndexPath.row];
[self.models replaceObjectAtIndex:sourceIndexPath.section withObject:model1];
[self.models replaceObjectAtIndex:destinationIndexPath.section withObject:model2];
}