一、UITableView简单介绍
1.tableView是一个用户可以滚动的多行单列列表,在表视图中,每一行都是一个UITableViewCell对象,表视图有两种风格可选
typedef NS_ENUM(NSInteger, UITableViewStyle) { UITableViewStylePlain, // regular table view UITableViewStyleGrouped // preferences style table view };
2.表视图还可为其添加索引值,比如通讯录中右侧索引列表,每一个索引项对应其节头标题
这两种形式的列表下面还会介绍到。
3.最简单的一种表视图是一个选择列表,可以限制选择一列或多列,如上图右边。
4.页眉和页脚,可以根据自己的需要,对tableView设置页眉和页脚的内容
二、UITableViewCell
1. UITableViewCell是表视图的单元格,系统会缓存可见的行。通过完成UITableViewDataSource协议中必须完成的代理方法CellForRowAtIndexPath方法来填充表视图上单元格数据。
2. UITableViewCell有四种样式可选
UITableViewCellStyleDefault, // 简单包含一个可选的imageView和一个label显示文本 UITableViewCellStyleValue1, // 包含可选的imageView,一个textLabel和一个detailLabel,其中detailLabel位置在最左,右对齐,文本颜色为蓝色 UITableViewCellStyleValue2, //包含一个textLabel和一个detailLabel,textLabel默认为蓝色文本,右对齐,detailLabel的位置紧挨着textLabel右边,默认文本左对齐,颜色为黑色 UITableViewCellStyleSubtitle // 包含可选的imageView,一个textLabel,一个detailLabel,其中detailLabel在textLabel下方,字体较小,默认颜色为黑色,左对齐
1. 先给出效果图
2. 创建方式及代码(本文只讲述代码创建)
a) 创建一个Single View Application,命名为"tableView"
b) 新建一个继承自UITableView的类,关于tableView的实现将全部写在这个类中(当然也可直接在对 应所需要用得ViewController中创建,分离出来的好处是可以在将tableView的方法单独放在一个类中,当ViewController的代码量比较大或者这个table需要在多个地方使用时推荐使用),命名为general_table_view.
c) 代码
①在general_table_view.h文件中,添加几个属性
@interface general_table_view : UITableView// tableView的坐标 @property (nonatomic, assign) CGRect tableViewFrame; // 存放Cell上各行textLabel值 @property (nonatomic, copy)NSMutableArray * textLabel_MArray; // 存放Cell上各行imageView上图片 @property (nonatomic, copy)NSMutableArray * images_MArray; // 存放Cell上各行detailLabel值 @property (nonatomic, copy)NSMutableArray * subtitle_MArray; @end
@interface general_table_view ()<UITableViewDataSource,UITableViewDelegate> @end
// Initialization code self.delegate = self; self.dataSource = self;
-(void)setTableViewFrame:(CGRect)tableViewFrame { self.frame = tableViewFrame;// 设置tableView的frame为所传值 }
必须实现的方法有两个
// tableView每个分区的行数,可以为各个分区设置不同的行数,根据section的值判断即可 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [_textLabel_MArray count]; } // 实现每一行Cell的内容,tableView重用机制 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 为其定义一个标识符,在重用机制中,标识符非常重要,这是系统用来匹配table各行cell的判断标准,在以后的学习中会体会到 static NSString *cellIdentifier = @"cellIdentifier"; // 从缓存队列中取出复用的cell UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; // 如果队列中cell为空,即无复用的cell,则对其进行初始化 if (cell==nil) { // 初始化 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; // 定义其辅助样式 cell.accessoryType = UITableViewCellAccessoryNone; } // 设置cell上文本内容 cell.textLabel.text = [_textLabel_MArray objectAtIndex:indexPath.row]; return cell; }
// tableView分区数量,默认为1,可为其设置为多个分区 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } // tableView页眉的值,同理,可为不同的分区设置不同的页眉,也可不写此方法 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return @"页眉"; } // 页脚 -(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { return @"页脚"; }
#import "general_table_view.h" @interface ViewController () { general_table_view *table;// 声明table } @end
// 初始化 table = [[general_table_view alloc] initWithFrame:CGRectMake(0, 20, 320, self.view.frame.size.height-20) style:UITableViewStylePlain]; // 设置数据源 table.textLabel_MArray = [[NSMutableArray alloc] initWithObjects:@"南京市",@"南通市",@"淮安市",@"镇江市",@"扬州市",@"常州市", nil]; [self.view addSubview:table];// 添加到当前View
// 初始化 table = [[general_table_view alloc] initWithFrame:CGRectMake(0, 20, 320, self.view.frame.size.height-20) style:UITableViewStyleGrouped];
在ViewController.m的ViewDidLoad方法中设置数据源时,在addSubview之前,初始化一个存放图片的数组,这里我添加的是同一张图片,如果想为每一行设置不同的图片,添加不同的图片到数组中即可
NSMutableArray *images = [NSMutableArray array]; for(NSInteger index = 0;index<[table.textLabel_MArray count];index++){ UIImage *image = [UIImage imageNamed:@"2"]; [images addObject:image]; } table.images_MArray = [[NSMutableArray alloc] initWithArray:images];
// 设置cell上文本内容 cell.textLabel.text = [_textLabel_MArray objectAtIndex:indexPath.row]; // 设置每一行的图片 cell.imageView.image = [_images_MArray objectAtIndex:indexPath.row];
五、列表的其他样式
在CellForRowAtIndexPath方法中,初始化Cell时改变cell的style和accessoryType,style,style默认有四种可选。
在ViewController的ViewDidLoad方法中添加图片的for循环中为数组添加值
NSMutableArray *subtitle= [NSMutableArray array]; for(NSInteger index = 0;index<[table.textLabel_MArray count];index++){ UIImage *image = [UIImage imageNamed:@"2"]; NSString *detail = [NSString stringWithFormat:@"detail text %d",index+1]; [images addObject:image]; [subtitle addObject:detail]; } table.subtitle_MArray = [[NSMutableArray alloc] initWithArray:subtitle];
UITableViewCellStyleDefault改变成其他三种样式,并添加代码// 设置小标题 cell.detailTextLabel.text = [_subtitle_MArray objectAtIndex:indexPath.row];
六、列表中行的操作
1.选中行
实现代理方法
// 选中行 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"您点击了第%d分区第%d行",indexPath.section, indexPath.row); // 取消选中状态 // [tableView deselectRowAtIndexPath:indexPath animated:YES]; }
要对行进行操作,首先要实现代理方法
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return YES; }
可重置删除按钮的标题,默认为"delete"
// 设置删除按钮标题 - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { return @"删除"; } 点击删除后- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // 从数据源中删除 [self.dataArray removeObjectAtIndex:indexPath.row]; // 从列表中删除 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; }
①这时我将插入行和删除行都以一个按钮动作来触发,点击后tableView进入编辑模式,先上效果图
②在ViewDidLoad中添加代码,其中self.addButton和self.deleteBarButtonItem均在storyBoard中创建,下文中的按钮也是这种情况
NSArray *leftBarButtons = [NSArray arrayWithObjects:self.addButton,self.deleteBarButtonItem, nil]; self.navigationItem.leftBarButtonItems = leftBarButtons;//设置导航栏左边按钮为添加和删除按钮
UITableViewCellEditingStyle selectEditingStyle;
// 更新导航栏按钮 -(void) updateBarButtons { if (self.tableView.editing==YES) { self.navigationItem.rightBarButtonItem = self.doneBarButtonItem; } } // 点击添加按钮 - (IBAction)addButtonClicked:(id)sender { selectEditingStyle = UITableViewCellEditingStyleInsert; [self.tableView setEditing:YES animated:YES]; [self updateBarButtons]; } // 点击删除按钮 - (IBAction)deleteButtonClicked:(id)sender { selectEditingStyle = UITableViewCellEditingStyleDelete; [self.tableView setEditing:YES animated:YES]; [self updateBarButtons]; }
// 是否可编辑 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } // 编辑模式 -(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { return selectEditingStyle; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // 删除模式 if (editingStyle==UITableViewCellEditingStyleDelete) { // 从数据源中删除 [self.dataArray removeObjectAtIndex:indexPath.row]; // 删除行 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } // 添加模式 else if(editingStyle == UITableViewCellEditingStyleInsert){ // 从数据源中添加 [self.dataArray insertObject:@"new iPhone" atIndex:indexPath.row]; // 添加行 [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic ]; } } // 点击完成按钮 - (IBAction)doneButtonClicked:(id)sender { [self.tableView setEditing:NO animated:YES]; [self updateBarButtons]; }
①效果图
②在tableView进入编辑模式时,可以对行进行移动操作,通过方法
// 是否支持移动 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } ③设置行可移动,并完成移动行方法,改变数据源// 移动行操作-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{// 这里其实就是数组中两个变量交换位置的过程 id object = [self.dataArray objectAtIndex:fromIndexPath.row]; [self.dataArray removeObjectAtIndex:fromIndexPath.row]; [self.dataArray insertObject:object atIndex:toIndexPath.row]; }
①即完成可以选择多个行之后批量删除,如图
②在ViewDidLoad中添加代码
self.navigationItem.rightBarButtonItem = self.editBarButtonItem;// 在右导航栏中添加编辑按钮
③现在需要达到,点击编辑按钮在右上角出现取消按钮,左上角出现删除按钮。并在选择时,能出现删除行的数量,修改updateBarButtons方法,并添加一个方法来根据条件修改删除按钮的标题
// 更新导航栏按钮 -(void) updateBarButtons { // 如果是允许多选的状态,即进入批量删除模式 if (self.tableView.allowsSelectionDuringEditing == YES) { //更新删除按钮 [self updateDeleteButtonTitle]; // 导航栏左边按钮设置为空 self.navigationItem.leftBarButtonItems = nil; // 将左边按钮设置为'批量删除'按钮 self.navigationItem.leftBarButtonItem = self.multiDeleteBarButton; // 导航栏右键设置为'取消'键 self.navigationItem.rightBarButtonItem = self.cancelBarButtonItem; return; } if (self.tableView.editing==YES) {// 如果是编辑状态,且不属于批量删除状态 // 导航栏右键设置为'取消'键 self.navigationItem.rightBarButtonItem = self.doneBarButtonItem; } else {// 如果不是编辑状态,将导航栏设置为初始状态的样式,即左栏为'添加','删除'按钮,右栏为'编辑'按钮 NSArray *leftBarButtons = [NSArray arrayWithObjects:self.addButton,self.deleteBarButtonItem, nil]; self.navigationItem.leftBarButtonItems = leftBarButtons; self.navigationItem.rightBarButtonItem = self.editBarButtonItem; } }// 更新删除按钮的标题 -(void)updateDeleteButtonTitle { NSArray *selectedRows = [self.tableView indexPathsForSelectedRows];//得到选中行 BOOL allItemsAreSelected = selectedRows.count == self.dataArray.count;// 是否全选 BOOL noItemsAreSelected = selectedRows.count == 0;// 选中行数是否为零 if (allItemsAreSelected || noItemsAreSelected) {// 如果是全选或者未选,则删除键为删除全部 self.multiDeleteBarButton.title = @"删除全部"; } else {// 否则 删除键为删除(选中行数量) self.multiDeleteBarButton.title = [NSString stringWithFormat:@"删除 (%d)", selectedRows.count]; } }
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath 两个方法中调用updateDeleteButtonTitle方法
// 编辑按钮 - (IBAction)editButtonClicked:(id)sender { self.tableView.allowsMultipleSelectionDuringEditing = YES;// 进入可多选删除状态 [self.tableView setEditing:YES animated:YES];// 将table设置为可编辑 [self updateBarButtons]; //更改导航栏的导航按钮 }
- (IBAction)multiDeleteClicked:(id)sender { // 选中的行 NSArray *selectedRows = [self.tableView indexPathsForSelectedRows]; // 是否删除特定的行 BOOL deleteSpecificRows = selectedRows.count > 0; // 删除特定的行 if (deleteSpecificRows) { // 将所选的行的索引值放在一个集合中进行批量删除 NSMutableIndexSet *indicesOfItemsToDelete = [NSMutableIndexSet new]; for (NSIndexPath *selectionIndex in selectedRows) { [indicesOfItemsToDelete addIndex:selectionIndex.row]; } // 从数据源中删除所选行对应的值 [self.dataArray removeObjectsAtIndexes:indicesOfItemsToDelete]; //删除所选的行 [self.tableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic]; } else { // 删除全部 [self.dataArray removeAllObjects]; [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic]; } // 删除完成,退出编辑状态,并退出多选状态,同时更新导航栏的按钮 [self.tableView setEditing:NO animated:YES]; self.tableView.allowsMultipleSelectionDuringEditing = NO; [self updateBarButtons]; }
本文向大家介绍实例讲解iOS应用开发中使用UITableView创建自定义表格,包括了实例讲解iOS应用开发中使用UITableView创建自定义表格的使用技巧和注意事项,需要的朋友参考一下 一、带索引目录的表视图 1.效果图 2.数据源 本想获取通讯录中得名字,但为了用模拟器调试方便,就写死了数据,所以也只写了部分字母,总之有那么点意思就成 3.显示索引 二、可以进行行标记的表视图 1.效果图
本文向大家介绍深入讲解iOS开发中的UIViewController,包括了深入讲解iOS开发中的UIViewController的使用技巧和注意事项,需要的朋友参考一下 UIViewController顾名思义:视图控制器。应该在MVC设计模式中扮演控制层的角色。一些初学者在最开始的时候一直不理解为何有了UIView还要UIViewController做什么用,不都是向视图中增加view。在此我
设计师Cento Lodigiani创建了一个很棒的video来演示这12个原则,用于一个有魅力的弹性立方体的简单对象。他也将这些例子转换成了一系列的GIF动图。
本文向大家介绍实例解析iOS中音乐播放器应用开发的基本要点,包括了实例解析iOS中音乐播放器应用开发的基本要点的使用技巧和注意事项,需要的朋友参考一下 一、调整项目的结构,导入必要的素材 调整后的项目结构如下: 二、新建两个控制器 (1)新建一个控制器,用于展示音乐文件列表界面,其继承自UITableViewController (2)新建一个控制器,用于展示播放界面,其继承自UIViewCo
本文向大家介绍举例讲解设计模式中的原型模式在iOS应用开发中的作用,包括了举例讲解设计模式中的原型模式在iOS应用开发中的作用的使用技巧和注意事项,需要的朋友参考一下 1 前言 在许多面向对象的应用程序中,有些对象的创建代价过于大或者过于复杂。要是可以重建相同的对象并作轻微的改动,事情会容易许多。我们可以通过轻微的改动重用已有的对象,以适应程序中的特定情况。今天我们就来学习一下该模式。 2 详述
本文向大家介绍iOS应用开发中UITableView的分割线的一些设置技巧,包括了iOS应用开发中UITableView的分割线的一些设置技巧的使用技巧和注意事项,需要的朋友参考一下 对于ios7,ios8及以上来说,调整UITableView的cell的分割线位置已经是相当不便,因为UITableView内部使用了margin layout. 其实只需要如下这样子就可以实现分割线的控制。 如果要