一.自定义Cell的步骤: (其实只要是自定义控件,都是这个步骤)
1.创建一个UITableViewCell 的 子类
2.重写初始化方法
3.把要添加的控件添加到cell的显示内容的区域:contentView
4.把系统的cell 改成自定义的cell
具体:
1.command + N 创建一个继承UITableViewCell的文件
2.重写初始化方法
- (instanceType)initWithStyle:(UITableViewCellStyle)reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
{
[self addSubView]; // addSubview里实现在cell上铺设控件的操作
}
return self;
}
3.addSubView 里实现自定义cell扑控件的过程
4.在调用Cell 的 视图控制器里面 , 在返回cell(展示数据)的那个协议方法里面: 改成自定义cell,具体如下:
- (UITableViewCell *)tableView : (UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 把之前 用UITableViewCell 创建的cell 全部改成 用自定义的Cell(MyTableViewCell 代替). 还可以通过Model数据模型中同一属性的不同的值来创建不同的自定义cell来铺设tableView
CellModel *model = self.dataArray[indexPath.row];
// 根据Model的值 来进行判断 : 显示不同的cell
if([model.gender isEqualToString:@"男"])
{ // 创建男的cell
static NSString *identifier = @"ManCell"; // 创建不同的标识符,让系统能够识别
ManTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if(cell == nil)
{
cell = [[ManTableViewCell alloc] initWithStyle:(UITableViewCellStyleSubtitle) reuseIdentifier:identifier];
}
// 给cell赋值 // 把cell的赋值过程封装起来了
cell.model = model; // 把model数据模型设置为cell的属性,那么,在给Model赋值的同时,咱们也希望给cell上的控件完成赋值
return cell;
}else
{
// 创建女的
static NSString *identifier = @"GirlCell";
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[MyTableViewCell alloc]initWithStyle:(UITableViewCellStyleSubtitle) reuseIdentifier:identifier];
[cell autorelease];
}
cell.model = model;
return cell;
tips:显示数据的时候的一个重要的点:
#pragma mark ------ 封装前的赋值方法
// // 显示数据
// CellModel *model = self.dataArray[indexPath.row];
// cell.nameLabel.text = model.name;
// cell.phoneLabel.text = model.phoneNumber;
// cell.genderLabel.text = model.gender;
// cell.imageV.image = [UIImage imageNamed:model.picture];
//
#pragma mark ------ 封装后的赋值方法
// 团队合作 :
// 在给Model赋值的同时, 咱们希望 也给cell上的控件完成赋值
// 我们只需要给出Model 就行了 ,
// 我们在自定义的cell中上面一个Model的属性,再重写setModel方法,在给Model属性赋值的时候,把cell上的控件也赋上值去
// CellModel *model = self.dataArray[indexPath.row];
// cell.model = model;
}
上面把cell的赋值给封装起来了
把Model设置为自定义cell的一个属性,给cell的Model赋值的时候,就给cell上的控件赋值,其实 就是要重写setModel方法
- (void)setModel:(CellModel *)model
{
if(_model != model)
{
[_model release];
_model = [model retain];
}
// 给cell赋值
self.nameLabel.text = model.name;
self.genderLabel.text = model.gender;
self.phoneNumber.text = model.phoneNumber;
}
二.label自适应文字
NSString *str = @"阿呆说大事了的哈舒服好烦啊说的放假啊说法哦发挥第四哦发给好卡仕达刷卡我放假啊是减法额条件啊神佛问而我啊身上饭卡额我空间让啊我'啊开发饿死客人确认[唉开发万恶太可恶情况[啊去看大苏打实打我'啊开发人气旺日是无法看到舒服可我却”;
// 先创建一个label
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100,100,200,300)];
label.backgroundColor = [UIColor redColor];
label.text = str;
label.numberOfLine = 0; // 设置完全显示,换行
label.font = [UIFont systemFontOfSize:16]; // 给定字体的大小
[self.view addSubview:label];
// 1.创建一个字体大小的字典
// 字典里的key:UIFont在系统中的属性名字NSFontAttributeName
// 字典里的value:label的font:上面给定好的
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:16],NSFontAttributeName,nil];
// 2.获取字符串 所占的区域
CGRect frame = [str boundingRectWithSize:(CGSizeMake(label.size.width,CGFLOAT_MAX)) options:options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil];
// 3.更改label的高度 (注意:frame 是结构体,不能直接用.修改,两个.的含义不同)
// 所以需要第三方
CGRect temp = label.frame; // 先把结构体拿出来
temp.size.height = frame.size.height; // 修改其中的高度进行修改
label.frame = temp; // 整体赋值
三.Cell的自适应
// 1.先在自定义cell里面添加一个计算字符串高度的方法
// 因为要被外部调用,所以写成累方法,且有返回值
+ (CGFloat)CellHeightForModel:(NewsModel *)model
{
// 创建字体大小的字典
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:16],NSFontAttributeName,nil];
// KSummaryWidth:是指summary对应的cell的label的宽度
CGRect textRect = [model.summary boundingRectWithSize:CGSizeMake(KSummaryWidth,CGFLOAT_MAX)options:options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil];
return textRect.size.height;
}
// 2.给cell上的控件label自适应高度
- (void)setModel:(NewsModel *)model
{
....//给model赋值,cell的控件赋值 (上面已经写过)
// 先获取这个控件上 字符串的高度
CGFloat summaryHeight = [MyTableViewCell CellHeightForModel:model];
// 改变summary所在的label的高度
CGRect temp = self.summary.frame;
temp.size.height = summaryHeight;
self.summary.frame = temp;
}
// 返回cell的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 取出对应 的model
NewsModel *model = self.dataArray[index.row];
// 计算高度
CGFloat SummaryHeight = [MyTableViewCell cellHeightForModel:Model];
// 上边距 + label1 + 中边距 + SummaryHeight + 下边距
return 40 + 50 + 40 + summaryHeight + 40;
}
四.解决cell的重用问题
1.在数据模型中设置是否选中的属性
// 标识选中的状态, 必须加在Model上,只有Model才能决定显示的内容
@property (assign,nonatomic)BOOL isSelected;
2.在加载数据的方法里:(就是把字典->数据模型的那个方法中)
创建每一个model的时候,对每一个model的选中属性设置初值为NO;
3.在点击方法中,根据选中的状态,来添加不同的图片
- (void)tableview:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 取出点击的model
NewModel *mode = self.dataArray[indexPath.row];
// 更改点击的状态
model.isSelected = !model.isSelected;
// 取出被点击的cell (这是系统方法)
MyTableViewCell *cell = (MyTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
// 判断状态
if(model.isSelected==YES)
{
cell.imageView.image = [UIImage imageNamed:@“select”];
}else
cell.imageView.image = [UIImage imageNamed:@“cancel”];
}
4.修改setModel方法 (防止复用时,状态混乱)
- (void)setModel:(NewsModel *)model
{
if (_model != model) {
[_model release];
_model = [model retain];
}
self.titleLabel.text = model.title;
self.summaryLabel.text = model.summary;
// 给图片赋值
// 利用Model中的点选状态解决cell复用的问题
// 需要每次被复用的cell时 进行与状态对应的赋值
if (model.isSelected == YES) {
self.imageV.image = [UIImage imageNamed:@"select"];
}else
self.imageV.image = [UIImage imageNamed:@"cancel"];
// 改变一下label 高度
// 自适应,在上面 …
}