自定义不等高cell,详解步骤
2015-08-28 22:47
169 查看
一.创建一个继承与UITableViewCell的类
在让这个类的.h文件拥有一个模型属性,在.m文件拥有子控件的类型属性,这样就可以在layoutSubviews和
set方法中拿到这些子控件,给它设置frame,赋值;
1.在下面方法中添加子控件
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { // 添加子控件 ******* } return self; }
2.在
layoutSubviews方法中设置frame;
- (void)layoutSubviews { [super layoutSubviews]; self.iconImageView.frame = self.status.iconFrame; self.nameLabel.frame = self.status.nameFrame; ******* }
3.在模型属性的set方法中给子控件设置数据
- (void)setStatus:(DXStatus *)status { _status = status; if (self.status.picture) { self.pictureImageView.hidden = NO; self.pictureImageView.image = [UIImage imageNamed:status.picture]; }else { self.pictureImageView.hidden = YES; } ******
注意:因为涉及到根据标识符循环利用cell,所以在给子控件中赋值时候要判断这个cell是否有这个子控件,有if 就一定有else.
并且
注意,是
else和
else if区别,
else意思是除了
if外的其他情况,而
else if是另外一种判断;表示还有其他可能情况;
二.新建一个模型
1.给模型添加子控件的frame属性,用于传递给新建的类2.给模型添加plist文件中相对应的属性;
3.给模型添加子控件的frame属性;
4.给模型添加(cellHeight)cell行高属性;
5.在模型中重写cellHeight的get方法,并在里面计算cell的行高;
比如:
@property (nonatomic, copy) NSString *picture; @property (nonatomic, assign) BOOL vip; @property (nonatomic,assign) CGFloat cellHeight; @property (nonatomic,assign) CGRect iconFrame; 声明属性需要特别注意:声明属性,起名字注意,不要跟系统自带的属性名字一样,比如在UITableViewCell中,它又一个imageView,那么你自定义UIImageView,不要用imageView作为属性名字,可以用iconImageView,如果你用这个imageView,可能会覆盖系统自带的属性,或者会出现问题,比如我用`UILabel *textLabel = [[UILabel alloc] init]`;那么UILabel系统内部有一个textLabel,这样会导致自己在给这个控件设置frame时候,出现和系统混乱问题,; 但是你可以用titleLabel,作为一个UILabel类型的名字,虽然UIButton内部有一个titleLabel属性,但是你现在没有用到UIButton 起名字要注意,一般要在后面加上控件的名称,比如声明一个UILabel类型的的属性,他名字最好是nameLabe,l
三.在控制器中需要做
1.更改viewController继承为UITableViewController2.删除storyboard,添加UITableViewController控制器,更改它类为viewController;
3.让控制器拥有一个数组属性,用来装模型;
4.懒加载--数组属性重写get方法,在这个方法判断,如果属性为空,就加载plist文件(mainBundle -->数组-->遍历数组-->新模型数组-->赋值给当前属性 ),
5.实现数据源方法
1.一共有多少行
tableView: numberOfRowsInSection:
2.每一行长什么样子,并传递
对应的模型数据给cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"status"; // 1.从缓存池中取 DXStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; // 2.如果缓存池没有,自己创建 if (!cell) { cell = [[DXStatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } // 3.传递对应的模型数据给cell cell.status = self.statuses[indexPath.row]; return cell; }
6.实现代理方法,返回对应行高;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { DXStatus *status = self.statuses[indexPath.row]; return status.cellHeight; }
难点:为什么要在模型中计算子控件和cell的高度?
因为cell的高度是由代理方法设置的,而这个代理方法调用顺序先于layoutSubviews这个方法,而我们的cell高度又是依据子控件的高度而不同计算出来,因此从layoutSubviews这个方法中计算子控件frame,拿到cell高度,不能给代理方法用,因为调用顺序代理方法调用顺序先于layoutSubviews这个方法,因此在模型中给它一个cell高度属性,在属性set方法中计算子控件,算出每一个cell高度,在代理方法中,利用(indexPath.row)取出对应的模型对象,直接返回模型对象的cell属性,那么就会调用模型中cellHeight属性的get方法,就能拿到cellHeight;技巧一:如果有的cell有图片,有的没有图片,先统一创建,然后再设置frame的时候进行判断,有的才给设置frame;
在set方法赋值的时候,也要进行判断这个cell是否有这个控件,如果有,就让它设置为显示,并进行赋值,如果没有,就让这个控件设置隐藏,不给它赋值;
技巧二:数据源方法的快速书写
一共有多少行这个方法
tableView:numberOfRowsInSection:
先写返回值
- (NSInteger)tableView就可过滤掉很多方法
每一行长什么样子
tableView: cellForRowAtIndexPath:
先写返回值
- (UITableViewCell *)tableView就可过滤掉很多方法
小知识点
1.contentView 和cell高度就差1,因为要显示分割线; 2.static NSString *ID = @“wine”; 用static修饰局部变量,这个局部变量就只创建一次,只分配一次内存,要不加static修饰字符串,每次调用这个方法就会重新创建一个局部变量; 不建议写外边,全局变量,会访问可以修改,但是注册某个标识,应该使用全局变量;
相关文章推荐
- Linux内核工程导论——进程
- 《我是奋青》打满鸡血让青春燃起来
- [C语言][LeetCode][219]Contains Duplicate II
- 不定义JQuery插件,不要说会JQuery
- Linux内核工程导论——基础架构
- 希尔排序(shell)
- java 如何将两个txt文件内容写入到一个txt文件中?
- 叶存菜鸟笔记之Set及Iterator一般应用和注意点
- C++中string的size,length,capacity三者到底有何区别求解啦?
- java中关于堆(heap)和栈(stack)的那点事
- 关于CodeFirst异常:无法确定类型'XXX'和类型‘YYY’之间的关联的主体端,必须使用关系 Fluent API 或数据注释显式配置此关联的主体端。
- Java,为项目而生
- 汇编中定义变量的形式
- JavaScript学习笔记之Array
- const
- 【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记44 Popover Segue
- FATE(二维完全背包)
- struts环境基本配置
- 面试经验分享
- 读取Excel的部分问题