1.创建UITableViewCell的子类
2.将添加到UITableViewCell的子视图设置为属性 同时将数据类也作为属性 方便给子视图进行赋值
#import <UIKit/UIKit.h>
#import "CellModel.h"
@interface NewsTableViewCell : UITableViewCell
@property (nonatomic ,retain) UILabel *titleLabel;
@property (nonatomic, retain) UILabel *summaryLabel;
// 选中图片
@property (nonatomic, retain) UIImageView *imageV;
@property (nonatomic, retain) CellModel *model;
@end
3.重写自定义初始化方法
- (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self addLabel];
}
return self;
}
// 添加子视图
- (void)addLabel
{
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake((kScreenWidth - 300) / 2, 20, 300, 40)];
self.titleLabel.backgroundColor = [UIColor orangeColor];
self.titleLabel.numberOfLines = -1;
self.titleLabel.font = [UIFont systemFontOfSize:16];
// 注意给UITableViewCell及其子类添加子视图时 需要添加到self.contentView上
[self.contentView addSubview:self.titleLabel];
[_titleLabel release];
self.summaryLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.titleLabel.left, self.titleLabel.bottom + 10, self.titleLabel.width, self.titleLabel.height)];
self.summaryLabel.backgroundColor = [UIColor grayColor];
// 多行显示
self.summaryLabel.numberOfLines = -1;
// 设置字体大小
self.summaryLabel.font = [UIFont systemFontOfSize:16];
[self.contentView addSubview:self.summaryLabel];
[_summaryLabel release];
self.imageV = [[UIImageView alloc] initWithFrame:CGRectMake(340, self.titleLabel.top + 5, 30, 30)];
[self.contentView addSubview:self.imageV];
[_imageV release];
}
4.重写model属性的setter方法
- (void)setModel:(CellModel *)model
{
if (_model != model) {
[_model release];
_model = [model retain];
}
// 在给model赋值的同时 给子视图进行赋值
self.titleLabel.text = model.title;
self.summaryLabel.text = model.summary;
// 在赋值的同时 改变label的高度(见下文)
// 获取字符串高度
CGFloat summaryHeight = [NewsTableViewCell cellHeightForModel:model];
// 改变一下label的高度
self.summaryLabel.height = summaryHeight;
}
5.在添加cell的方法中用该类初始化对象cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"MyCell";
NewsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[NewsTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier] autorelease];
}
CellModel *model = self.arrData[indexPath.row];
// 直接赋值 将具体赋值过程封装在NewsTableViewCell类中进行
cell.model = model;
return cell;
}
用于改变存放字符串的label的高度, 通常在UITableViewCell的子类中实现
// 计算字符串的高度(类方法)
+ (CGFloat)cellHeightForModel:(CellModel *)model
{
// 创建字体大小的字典
// 这里设置了字体大小后 需要label的font属性做相应的改变
NSDictionary *fontDic = @{NSFontAttributeName: [UIFont systemFontOfSize:16]};
CGRect textRect = [model.summary boundingRectWithSize:CGSizeMake(300, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:fontDic context:nil];
return textRect.size.height;
}
当然 不光要改变label的高度 同时需要改变cell的高度
// 行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CellModel *model = self.arrData[indexPath.row];
CGFloat tempHeight = [NewsTableViewCell cellHeightForModel:model];
// 上边距 + tilteLabel + 中间距离 + summaryLabel + 下边距
return 20 + 40 + 10 + tempHeight + 20;
}
给cell 添加一个UIImageView 点击cell时 UIImageView.image 变成选中图片 再次点击cell 时UIImageView.image 变回未选中图片
当然不能直接在方法中更改图片 这样子再次点击无法变回未选中图片
因此需要给model添加 isSelected 属性 来记录对应的cell的点击状态
在tableView 用 CellModel 类 “获取” 数据文件的字典数据的同时 应该给model.isSelected属性赋一个初值 而cell一开始应该显示未选中图片 所以:model.isSelect = NO;
- (void)setUpData
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"NewsData" ofType:@"plist"];
NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *values = dic[@"news"];
self.arrData = [NSMutableArray array];
for (int i = 0; i < values.count; i++) {
CellModel *model = [[CellModel alloc] init];
[model setValuesForKeysWithDictionary:values[i]];
***model.isSelect = NO;***
[self.arrData addObject:model];
[model release];
}
}
当然此时为了使cell在程序运行开始时呈现未选中图片 需要在给cell.model
赋值的同时 给 imageView
添加一个图片 但是并不是直接给他一张未选中图片 如果这样做了 那么从重用集合中取出的cell即使是选中状态 也会在 重新赋值时变回未选中状态
我们不想在屏幕上滑时出现这样的问题 所以需要在赋值过程中判断一下(赋值过程当然还在cell的子类中进行)
- (void)setModel:(CellModel *)model
{
if (_model != model) {
[_model release];
_model = [model retain];
}
// 利用model中的点选状态 解决cell复用的问题
// 需要每次被复用的cell 再进行一次与状态对应的赋值
if (model.isSelect == YES) {
self.imageV.image = [UIImage imageNamed:@"select"];
}else{
self.imageV.image = [UIImage imageNamed:@"cancel"];
}
}
在点击方法中根据选中属性model.isSelect
来给cell 的 ImageView 更换图片
// cell 点击的方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 取出被点击的cell
// 更改cell 图片
NewsTableViewCell *cell = (NewsTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
CellModel *model = self.arrData[indexPath.row];
// 更改点击的状态
model.isSelect = !model.isSelect;
if (model.isSelect == YES) {
cell.imageV.image = [UIImage imageNamed:@"select"];
}else{
cell.imageV.image = [UIImage imageNamed:@"cancel"];
}
}