031-UITableView(2)-iOS笔记

学习目标

1.【掌握】xib自定义cell之团购案例

2.【掌握】代码自定义cell之微博案例

一、xib自定义cell之团购案例

UITableViewCell提供了四种Cell样式,但是自带的样式往往不能满足我们的开发需求。当系统自带cell样式不能满足我们开发需求时,就应该自己手动创建cell。

手动创建cell的两种方式:

当cell的布局样式相同,只是数据不同我们就可以使用xib快速创建cell。

当布局样式不同的时候,我们就不能使用xib来创建cell,而是需要重写初始化cell的方法代码创建cell。

先了解下简单的xib快速创建cell案例,我们需要做一个团购商品展示页面,如下图所示:点击这里查看动态图

031-UITableView(2)-iOS笔记

需求:顶部有图片轮播,中间是商品列表,底部有加载更多按钮并且点击后能加载新的cell。

分析:从截图可以看出每个cell的布局都是相同的,有商品图片、名称、价格、购买数量。所以我们可以使用xib来创建,头部轮播器以前以后做过了,这里就不重点解释。今日、明日、后日推荐按钮和图片轮播是一个view。底部加载更多也是一个单独View,不过他们都随着tableview一起滚动,所以他们都是在tableview中。

首先不考虑界面,先创建项目导入素材和plist文件,并封装模型对象。

031-UITableView(2)-iOS笔记

JFGoods.h

JFGoods.m

封装好模型后,创建xib文件。注意这里是UITableViewCell控件而不是UIView,因为只有UITableViewCell才能设置cell重用标识符

031-UITableView(2)-iOS笔记

创建好xib后就创建封装cell类,注意这个类是继承自UITableViewCell。然后再xib的Custom Class选项中制定Class为我们创建的类,再进行控件属性拖线。然后定义对应方法,加载xib并创建创建cell,再对其进行子控件赋值数据。

031-UITableView(2)-iOS笔记

JFGoodsCell.h

JFGoodsCell.m

顶部的UIView我使用了网上下载的类库快速创建,类库地址:https://github.com/gsdios/SDCycleScrollView 。下载类库,并导入我们的工程,再使用xib来创建一个UIView,在UIView中再创建一个用于展示轮播的UIView并进行控件属性连线,然后将创建好的轮播器添加到这个UIView中。

031-UITableView(2)-iOS笔记

提供一个快速创建顶部View的类方法,并实现。

JFHeaderView.h

JFHeaderView.m

效果如图所示:

031-UITableView(2)-iOS笔记

底部也是一个单独的UIView,也可以使用xib来创建。默认能点击,说明有一个Button,点击后Button隐藏Button并显示一个菊花转的控件和Label。拖好控件然后再进行LoadingView和LoadingBtn的属性连线。

031-UITableView(2)-iOS笔记

加载更多数据的思路分析

点击按钮后不仅仅是能隐藏按钮、显示加载View,还能实现真正的加载数据功能。要实现这个功能,我们必须要用到当前的tableview和模型数组,并能修改模型数组。

如果将控制器作为方法参数传递过来也是可以实现的,但是这不符合MVC设计思想,所以我们将控制器设为代理来帮我们完成控制器才能完成的事情。

给按钮添加单击事件,调用代理方法。在点击了按钮后,会触发单击事件,调用self中的方法来完成数据添加功能。

JFFooterView.h

JFFooterView.m

完成了封装数据模型、封装Cell、创建顶部和底部UIView后,最后来控制器进行各种调用。先在Main.storyboard中拖拽一个满屏的UITableView控件并进行属性连线操作。最后再控制器中加载数据、创建cell并实现加载更多数据的代理方法。

ViewController.m

案例易错总结:

1.通过plist加载模型数据,Controller中懒加载数据,设置tableview的数据源和代理对象。

2.默认情况xib和视图类是不能进行连线操作的,需要在xib中指定自定义类。

3.要给xib中的控件赋值,就必须把模型对象传递给cell,可以设置方法或直接定义模型属性。

4.加载xib创建cell时要注意xib不能加后缀名,并且是返回数组最后一个元素。

5.整个案例以MVC模式来设计,设置MVC逻辑group分类管理。

6.底部View加载更多数据用代理来完成,不要把控制器传递给底部View类。

二、代码自定义cell之微博案例

当每个cell的结构样式不同的时候,我们就不能使用xib来快速创建cell,而是通过代码创建控件来创建cell。我们通过一个微博案例来演示代码创建cell的方法,下图就是微博案例完成后的截图:点击这里查看动态图

031-UITableView(2)-iOS笔记

需求:实现微博消息界面,每个人都有头像且尺寸一样,每个人都有名字字数不一定相同,有vip就显示皇冠没有就不显示,正文自动换行,有配图就显示配图没有就不显示。

分析:从上图可以看出,cell中应该有头像、昵称、vip、正文、配图控件。且每个控件之间有个固定间距,vip的frame根据昵称的x坐标来决定,正文的高度决定了配图的坐标,配图尺寸可以定死。由此可得知,昵称、正文需要计算宽、高,并且是根据昵称的字数、字体来计算。

导入素材和plist文件,并封装模型。注意这里字典中国键值对个数不是统一的,有些没有picture,但我们封装的时候按照最多键值对的字典来定义属性。因为属性都有默认值,如果是NSString则默认为nil,将nil赋值给控件并不会对程序造成影响。

031-UITableView(2)-iOS笔记

JFWeibo.h

 JFWeibo.m

代码自定义cell的高度每行都不同,所以一般不能通过tableView.rowHeight属性来定义。我们需要根据每个cell子控件的frame计算每个cell的高度,并且需要通过UITableView的代理方法来指定每个cell的高度。

但是:指定cell高度的代理方法是在创建调用创建cell的方法之前调用的,也就是我们需要在创建cell之前就计算出cell子控件的frame和cell的高度

这个UITableView的代理方法返回每个cell的高度,执行优先级高于下面返回cell的方法。

这个UITableView的数据源方法返回cell,但是他的调用优先级比上面的代理方法优先级低,也就是后执行这个方法。

通过上面的分析得之,我们需要在创建cell之前计算好cell子控件的frame和cell的高度。所以我们封装一个cell的frame模型类,通过模型数据来计算cell子控件的frame和cell的高度

JFWeiboFrame.h

 JFWeiboFram.m

封装好cell的frame后就开始封装cell,因为我们每个cell的布局样式不同,所以只能使用代码创建子控件自定义cell。封装cell的类中不需要模型属性,直接定于frame模型属性就行了,因为frame模型属性中就有模型属性。

JFWeiboFrame.h

 注意我们需要重写initWithStyle:reuseIdentifier:方法创建cell的子控件,因为系统自带的cell样式和xib都不能使用,只能代码创建cell的子控件来展示数据。

JFWeiboFrame.m

封装好cell后,我们就可以开始在控制台调用了。首先先在Main.storyboard中删除原有的控制器,拖拽一个新的控制器控件UITableViewController。这样做的好处是我们不需要手动添加UITableView数据源、代理协议,手动指定数据源、代理对象,会默认帮我们设置好这一切

031-UITableView(2)-iOS笔记特别注意的是:必须勾选Is initial View Controller选项,让当前控制器设为默认视图控制器,否则看不到界面。

031-UITableView(2)-iOS笔记

最后在控制器中定义一个frame模型数组属性并懒加载数据,然后实现数据源方法和代理方法,创建cell并为cell赋值数据。

ViewController.m

案例易错总结:

1.创建cell的子控件是在重写initWithStyle:reuseIdentifier:方法中创建。

2.封装frame模型的意义就是为了计算cell的高度,因为设置高度的代理方法优先级高于创建cell的数据源方法。

3.使用UITableViewController控制器,可以节省我们遵循协议、指定代理的步骤。

六阿哥

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: