iOS开发之UI开发(UITableView)
UITableView
继承自
UIScrollView
,性能极佳
UITableView
的两种样式UITableViewStylePlain
列表样式UITableViewStyleGrouped
分组样式
dataSource的代理
UITableView
需要一个数据源datasource
来显示数据UITableView
会向数据源查询一共有多少行数据以及每一行显示什么数据等- 没有设置数据源的
UITableView
只是个空壳 - 凡是遵守
UITableViewDataSource
协议的OC对象,都可以是UITableView
的数据源
设置数据源
方法1代码
ViewController添加协议UITableViewDataSource
@property(weak,nonatomic) IBOutlet UITableView *tableView;
self.tableView.dataSource = self;
方法二拖线
UITableView 右键 -> dataSource -> 拖到ViewController
实现协议的方法,有两个必须实现
//告诉UITableView 显示几组,不实现默认分1组,可以不实现
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{return 1;
}//告诉UITableView每组显示几行数据,必须实现
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{return 2;
}//告诉UITableView每一组的每一行显示什么单元格内容,必须实现
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];cell.textLabel.text = @"hello";//cell.imageView//cell.detailTextLabel.textreturn cell;
}
cell
的属性
cell.textLable.text
显示文字
cell.imageView
显示图片
cell.detailTextLabel.text
显示小文字
cell
的Style
可以修改cell的多种显示
UITableView多组数据
先设置UITableView
的Style
为Grouped
//告诉UITableView 显示几组,不实现默认分1组,可以不实现
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{return 3;
}//告诉UITableView每组显示几行数据,必须实现
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{//根据不同组显示不同行数据
if(section == 0){return 3;}
else if(section == 1){return 2;}
else{return 1;}
}//告诉UITableView每一组的每一行显示什么单元格内容,必须实现
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath{UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];if(indexPath.section == 0){//第一组if(indexPath.row == 0){cell.textLable.text = @"中国";}//第一行else if(indexPath.row == 1){cell.textLable.text = @"韩国";}//第二行else{cell.textLable.text = @"韩国";}
}
else if(indexPath.section == 1){if(indexPath.row == 0){cell.textLable.text = @"南非";}//第一行else(indexPath.row == 1){cell.textLable.text = @"索马里";}//第二行
}
else{cell.textLable.text = @"荷兰";}return cell;
}//每一组的标题显示什么
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInsection: (NSInteger)section{//section返回不同组的标题
if(section == 0){return @"亚洲";}
else if(section == 1){return @"非洲";}
else{return @"欧洲";}
}//每一组的描述,组尾
-(NSString *)tableView: (UITableView *)tableView titleForFooterInSection: (NSInteger)section{if(section == 0){return @"亚洲的描述";}
else if(section == 1){return @"非洲的描述";}
else{return @"欧洲的描述";}
}
动态加载plist文件到UITableView
MVC:plist
转模型
先设置UITableView
的Style
为Grouped
#import <Foundation/Foundation.h>
@interface CZGroup: NSObject//组标题
@property(nonatomic,copy)NSString *title;
//组描述
@property(nonatomic,copy)NSString *desc;
//这组里面的汽车品牌信息
@property(nonatomic,strong)NSArray *cars;-(instancetype)initwithDict: (NSDictionary *)dict;
+(instancetype)groupWithDict: (NSDictionary *)dict;
@end@implementation CZGroup
-(instancetype)initwithDict: (NSDictionary *)dict
{ if(self=[super init])//调用父类的初始化{[self setValuesForKeysWithDictionary:dict];}return self;
}
+(instancetype)groupWithDict: (NSDictionary *)dict
{return [[self alloc]initWith:dict];}
@end
@property(nonatomic,strong)NSArray *groups;-(NSArray *)groups{if(_groups == nil){NSString *path = [[NSBundle mainBundle]pathForResource:@"car_simple.plist" ofType:nil];NSArray * arrayDict = [NSArray arrayWithContentsOfFile:path];NSMutableArray *arrayModel = [NSMutableArray array];for(NSDictionary *dict in arrayDict){GZGroup *model = [CZGroup groupWithDict:dict];[arrayModel addObject:model];}_group = arrayModel;}return _groups;
}
//告诉UITableView 显示几组,不实现默认分1组,可以不实现
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{return self.groups.count;
}//告诉UITableView每组显示几行数据,必须实现
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{//根据不同组显示不同行数据GZGroup *group = self.groups[section];return group.cars.count;
}//告诉UITableView每一组的每一行显示什么单元格内容,必须实现
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath{GZGroup *group = self.groups[indexPath.section];//第几组 NSString *brand = group.cars[indexPath.row];//第几行UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];cell.textLabel.text = brand;cell.accessoryType = UITableViewCellAccessoryCheckmack;return cell;
}//每一组的标题显示什么
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInsection: (NSInteger)section{GZGroup *group = self.groups[section];return group.title;
}//每一组的描述,组尾
-(NSString *)tableView: (UITableView *)tableView titleForFooterInSection: (NSInteger)section{GZGroup *group = self.groups[section];return group.desc;
}
cell
设置右边点击按钮
//多种选择,枚举
cell.accessoryType = UITableViewCellAccessoryCheckmack;//打钩
cell.accessoryType = UITableViewCellAccessoryDetailButton;//详情
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;//小箭头
类型是UIView
cell.accessoryView = [[UISwitch alloc] init];//可以自定义
UITableViewCell的常见属性
lmageView
显示图片textLabel
显示文字detailTextLabel
显示小文字accessoryType
右边单元格类型选择accessoryView
右边单元格自定义backgroundColor
设置单元格背景backgroundView
设置背景图片,可以指定一个UIImageViewselectedBackgroundView
设置背景被选中图片
设置背景被选中改变颜色
UIView *bgView = [[UIView alloc] init];
bgView.backgroundColor = [UIColor greenColor];
cell.selectedBackgroundView = bgView;
rowheight
统一设置行高(也可以不设置)
self.tableView.rowheight = 60;
- 每行行高不一致的设置方法
1.添加代理,<UITableViewDelegate> 跟Source不是同一个
2.代理方法
-(CGFloat)tableView:(tableview *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath{int rownum = indexpath.row;if(rownum %2 == 0) {return 60;}else{return 120;}
}
separatorColor
分割线颜色
self.tableView.separatorColor=[UIColor redColor];
separatorStyle
分割线样式
self.tableView.separatorStyle=UITableViewCellSeparatorStyleNone;//没有分割线
- 设置分割线的
Insets
上下左右间距
[self.tableView setseparatorInset:UIEdgeInsetsMake(0,0,0,0)];
tableHeaderView
最上方一般可以放广告tableFooterView
最下方一般可以放加载更多
UITableView的性能优化(cell的循环利用)
UITableView
的加载数据的本质是,加载将要进入画面中的cell
,释放离开画面的cell
,但是需要多次重复的创建和释放对象
因为每次都创建一个单元格效率比较低,所以要对单元格进行重用,单元格重用的基本思路就是:
- 1:在创建单元格的时候指定一个“重用ID”
reuseIdentifier
- 2:当需要一个新的单元格的时候,先去"缓存池”中根据“重用ID”
reuseIdentifier
去查找是否有可用的单元格 - 如果有,则直接从缓存池中取出这个单元格,进行使用(修改这个单元格中显示的数据、样式 )
- 如果没有需要的单元格,此时只能重新创建件一个单元格了
//告诉UITableView每一组的每一行显示什么单元格内容,必须实现
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath{//声明一个static IDstatic NSString *ID = @"hero_cell";//根据这个重用ID去缓存池查找对应的CellUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];//没有找到cell,那就重新创建一个//现在好像不需要这个步骤了,可以直接dequeueReusableCellWithIdentifier:ID就行了//if(cell==nil){// UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];//}return cell;
}
设置右侧索引
- 实现右侧的索引栏,通过实现数据源协议的方法
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
点击右侧索引栏中的文字,会根据索引的顾序跳转到左侧对应的位置,获取groups数组中的每个对象的tite值,并返回到一个NSArray中
//该方法运行一次
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{//返回array数组的每个元素对象的属性
return [self.groups valueForKeyPath:@"title"];
}
滚动到最后一行
NSIndexPath *idxPath = [NSIndexPath indexPathForRow:10 inSection:0];
//该行滚动到最上面
[self.tableView scrollToRowAtIndexPath:idxPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]
代理监听点击cell
遵守UITableViewDelegate
协议
代理方法:
//监听行被选中的代理方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath{NSLog(@"%ld",(long)indexPath.row);
}
代理监听滚动
- 遵守代理协议
//滚动的时候执行该方法
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{}
修改cell内容并刷新
找到数据源模型 -> 修改属性 -> 刷新tableView
NSString *name = @"text";
CZHero *hero = self.hero[0];
hero.name = name;//刷新数据,重载,全部刷新
[self.tableView reloadData];
//局部刷新,可以刷新指定的行或是组,不能用于添加数据后刷新
NSIndexPath *idxPath = [NSIndexPath indexPathForRow:1 inSection:0];//inSection组,Row行
[self.tableView reloadRowAtIndexPaths: idxPath withRowAnimation:UITableViewRowAnimationAutomaic];
//withRowAnimation枚举可以选择刷新动画
从别的控件修改,可以通过tag
传值
xib自定义cell
- 建一个空的
xib
文件 -> 添加cell
控件 ->cell
控件内自己添加 - 参考iOS开发之UI开发2 ->
xib
- 可重用ID可以在xib文件中修改
identifier
,或者代码实现
tableFooterView最下方的view
tableFooterView的
frame
只能修改x和height
的值,Y和width
不能修改
ActivityindicatorView加载指示器
ActivityindicatorView转动
:ActivityindicatorView
->Behavior
->Animating
UITableViewController
可以替代
ViewController
,tableView和代理已经设置好了
- 设置
ViewController
->is inltial View Controller
为启动控制器 - 设置
UITableViewController
的class
继承自UITableViewController
自定义cell
- 继承自
UITableViewCell
- 重写构造函数
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentfier{if(self = [super initWithStyle:style reuseIdentifier:reuseIdentfier]){//添加组件UIImageView *imgViewIcon = [[UIImageView alloc] init];[self.contentView addSubview:imgViewIcon];...}return self;
}
-(void)settingData{//转模型时判定是否有,有就展示出来if(model.piture){self.imgViewpicture.image = [UIImage imageNamed:model.picture];self.imgViewpicture.hidden = NO;}else{self.imgViewpicture.hidden = YES;}...}
-(void)setView{[self settingdata];
}
计算文字NSSrting的frame
- 根据昵称的文字计算昵称
label
的宽和高 - 影响昵称
Label
的高和宽的因素:字体大小、文字多少、高度取决于是否固定了宽度(是否限制了最大的宽度和高度)
CGSize name = [字符串对象 boundingRectWithSize: CGSizeMake(MAXFLOAT,MAXFLOAT) options: NSStringDrawingUsesLineFragmentOrigi attributes: @{NSFontAttributeName:[UIFont systemFontOfSize:12]} context: nil].size;CGFloat nameW = name.width;
CGFloat nameH = name.height;boundingRectWithSize:最大的大小,一般取CGSizeMake(MAXFLOAT,MAXFLOAT),没有限制
options:计算方式
attributes:获取字体大小,存放字典形式,@{NSFontAttributeName:[UIFont systemFontOfSize:12]}
- 保证这里计算的时候使用的字体大小和创建
Label
时设置的字体大小一致,使用一个宏来统一设置 - 根据呢称
Label
的宽和高,计算x和y
进阶:可以为NSString加类方法,更加方便
-(CGSize)size0fTextWithMaxSize:(CGSize)maxSize font:(UIFont *)font{NSDictionary *attrs =@{NSFontAttributeName:font};return [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes: attrs context: nil].size;}+(CGSize)sizeWithText:(NSString *)text maxSize: (CGSize)maxSize font: (UIFont*)font{[text sizeOfTextWithMaxSize:maxSize font:font];
}
计算cell的高度
- 需要先算完再生成
cell
,所以需要提前到懒加载的时候,把行高等数据先算好 - 写一个
modelView
,model
成为他的属性之一,懒加载时全部计算好
CGFloat rowHeight = 0;
//判断是否有最后一个组件,由最后一个组件的Y决定
if(self.weibo.picture){rowHeight = CGRectGetMaxY(self.imgViewPicture.frame)+margin;
}else{rowHeight = CGRectGetMaxY(self.lblText.frame)+margin;
}
//返回行高
-(CGFloat)tableView:(tableview *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath{CZFrame *frame = self.Frames[indexPath.row];return frame.rowHeight;
}
统一设置每组标题的行高
- 控制器
viewDidLoad
方法
-(void)viewDidLoad{[super viewDidLoad];//统一设置每组的组标题的高度self.tableView.sectionHeaderHeiaht = 44;
}
取消UITabelView的选中高亮
tableView.allowsSelection = NO;
静态UITableView
就是代码写死的
UITableView
,在storyboard
里面设计
- 在设置
content
选择static cell,
需要注意的是,需要使用UITableViewController
,而不是ViewController
设置titleForHeader的两种形式
//方法一:设置每一组的标题
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInsection: (NSInteger)section{GZGroup *group = self.groups[section];return group.title;
}
-为了重用,这里建议使用UITableViewHeaderFooterView
,cell
外,header
和footer
都要遵循重用模式
//方法二:带有控件的标题
-(UIView *)tableView:(UITableView *)tableview viewForHeaderInsection:(NSInteger)section{GZGroup *group = self.groups[section]; //为了重用,这里建议使用UITableViewHeaderFooterView,可以将其封装//声明一个static IDstatic NSString *ID = @"group_header_view";//根据这个重用ID去缓存池查找对应的headerVm UITableViewHeaderFooterView *headerVm = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID];//没有找到headerVm,那就重新创建一个if(headerVm == nil){headerVm = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:ID];}//设置数据return headerVm;
}
控件的frame发生改变调用的方法
-(void)layoutSubviews{[super layoutSubviews];
//自己的代码
}
下拉刷新
UITableView
设置 ->refreshing
-> 启用 ->方法返回值改为IBAction
->
控件和方法进行连线
连线完默认设置下拉执行self.refreshControl
的开始执行方法
- 在
ViewController
中重写方法
self.refreshControl.tintColor = [UIColor blueColor];
self.refreshControl.attributedTitle = [[NSAttributedString alloc]initWithString:@:"正在加载..." attributes:@{NSForegroundColorAttributeName:[UIColor redColor]}];
- 刷新结束执行该方法
[self.refreshControl endRefreshing];
cell左滑删除
让tableView进入编辑模式,新增代理方法
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{//点击哪个cell的delete,就执行//数据源中删除该行//可以刷新tableView,也可以执行这个方法,会有动画//deleteRowAtIndexPaths:是Array类型//withRowAnimation:动画效果自己选[self.tableView deleteRowAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];//该方法执行完会自动比较数据源和显示出来的数据量是否一致(务必先删除模型)//删除方法
}
xib中Cell的复用
//在viewDidLoad中注册
[tableView registerNib:[UINib nibWithNibName:@"FDBlackListTableCell" bundle:nil] forCellReuseIdentifier:@"FDBlackListTableCell"];
//代理方法中
FDBlackListTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FDBlackListTableCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
iOS开发之UI开发(UITableView)相关推荐
- IOS开发之UI基础LOL英雄展示-15
IOS开发之UI基础LOL英雄展示-15 // // ViewController.m // 15-英雄展示-单组数据 // // Created by 鲁军 on 2021/2/3. //#impo ...
- (0010) iOS 开发之UI布局兼容 4s/5/6/7 屏幕解决方案
iOS开发技术分享群 147787076 如上带标注的效果图,是1080*1920 也就是6p 的尺寸.如何根据6p的标注,在各种iPhone 尺寸上完美适配尼? 适用:UI 各屏幕/分辨率适配方案( ...
- iOS开发之SDK开发
转自 https://www.jianshu.com/p/cbb1f54b89d2 内容提要:不同场景下如何封装及开发SDK .a静态库创建 直接创建Framework库 在已有工程中创建 创建Fra ...
- (0107)iOS开发之UI实时调试InjectionIII的使用
AppStore : 下载:Injectionlll 下载地址 使用步骤: 1.设置InjectionIII 打开InjectionIII工具,选择Open Project,选择你的代码所在的路径,然 ...
- IOS开发之UI手势
2019独角兽企业重金招聘Python工程师标准>>> 点击手势和双击手势 #import "TapViewController.h" @interface Ta ...
- (0061)iOS开发之iPad开发:UISplitViewController分割视图控制器
//分割试图控制器 左侧默认320宽度 右侧self.view.frame.size-320 @property (strong,nonatomic)UISplitViewController *sp ...
- iOS开发之AVKit框架使用
2019独角兽企业重金招聘Python工程师标准>>> iOS开发之AVKit框架使用 一.引言 在iOS开发框架中,AVKit是一个非常上层,偏应用的框架,它是基于AVFounda ...
- 李洪强iOS开发之RunLoop的原理和核心机制
李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...
- iOS开发之ARC(自动引用计数)
iOS开发之ARC(自动引用计数) 英文原文:Automatic Reference Counting on iOS 参与翻译(4人): 纶巾客, showme, 李远超, 王宇龙 自动引用计数(AR ...
最新文章
- 【BZOJ】1299: [LLH邀请赛]巧克力棒
- vscode中调试react
- 使用response的outputstream
- java jbutton 不显示_java – JButton中的图像未显示
- easyexcel 设置标题_使用easyexcel完成复杂表头及标题的导出功能(自定义样式)
- 【ElasticSearch】Es 源码之 Exporters 源码解读
- 论文公式编号右对齐_如何编辑处理论文中的公式
- 开源cnc软件_带有开源软件的CNC铣削
- Layui表格点击详情
- 用C语言实现推箱子小游戏基础程序
- 设计网站制作步骤是什么?一个好的网站制作标准是怎样的?
- mysql创建新用户
- 爬壁机器人外文文献_仿生爬壁机器人的研究现状
- 如何与宜家IKEA建立EDI连接?
- CVPR 2020 开幕!最佳论文奖等揭晓!
- 计算机主板上一般带有高速缓冲存储器cache,它是与什么之间的缓存,计算机微机原理与应用(一)...
- android 仿简书评论,Android 开发仿简书登录框可删除内容或显示密码框的内容
- python最大递归层次_练习题-Python的最大递归层数
- HSV与RGB之间相互转换
- Win10 x64 中VC6 安装卡死、无法单步调试、调试退出进程没有结束