UI一揽子计划 11 (自定义UITableViewCell、Cell 的自适应高度)

一. 自定义UITableViewCell
在日常的编程中,系统提供的几种Cell 样式 往往不能满足我们的需求.所以需要我们给它进行自定义样式.
自定义Cell 就是创建一个UITableViewCell 的子类.把Cell 上的空间都封装在子类中,简化UIViewController上的代码 .   子视图空间添加到Cell 的ContentView 上面.
Cell 中声明一个Model类型的属性,ViewController中获取到Model对象后赋值给Cell 的Model属性
Cell 中重写Model 的setter 方法 把Model对象中的内容重新赋值给各个控件.
M和V之间不直接进行通信,C负责M和V之间进行通信.
通常我们会在 tableView:cellForRowAtIndexPath: ⽅方法中根据不同的
Model 来决定使⽤用什么类型的 cell 每种类型的 cell 要定义不同的重⽤用标识符 cell 重⽤用的时候会根据重⽤用标识从重⽤用队列中取⽤用哪种类型的 cell

自定义 Cell 的步骤
    1. 创建一个继承自UITableViewCell 的类
   2. 重写初始化方法
   3. 在初始化方法中 把需要的视图添加在 self.contentView 上面
   4. 未完待续 ( tableView 上面完成的 )
      UITableView 里面把系统的 UItbleViewCell 换成我们定义好的 GodGirlCell

在Cell自定义中重写
- ( void )setModel:( GodGirlModel *)model
{
   
if ( _model != model) {
        [
_model retain ];
       
_model = [model retain ];
    }
   
self . nameLabel . text = self . model . name ;
   
self . genderLabel . text = self . model . gender ;
   
self . hobbyLebel . text = self . model . hobby ;
   
self . phoneLabel . text = self . model . phoneNumber ;
   
}
UITableView 里面把系统的 UItbleViewCell 换成我们定义好的 GodGirlCell

- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
//    static NSString *identifiter = @"GodGirlCell";
//    GodGirlCell *cell = [tableView dequeueReusableCellWithIdentifier:identifiter];
//    if (cell == nil) {
//        cell = [[[GodGirlCell alloc]initWithStyle:(UITableViewCellStyleSubtitle) reuseIdentifier:identifiter]autorelease];
//    }
显示数据 1
//    GodGirlModel *godGirl = self.array[indexPath.row];
//    cell.godGirlimageview.image = [UIImage imageNamed:@"nvshen"];
//    cell.nameLabel.text = godGirl.name;
//    cell.hobbyLabel.text = godGirl.hobby;
//    cell.phoneLabel.text = godGirl.phoneNumber;
显示数据 2
    // model 传进 Cell 内部进行赋值
    // model 进入 cell 内部
   
// 通过重写 model set 方法
   
GodGirlModel *godGirl = self . array [indexPath. row ];
// 利用 model 的属性选择 显示不同的 cell
   
一个tableView 显示多种cell思路:

    1. 创建多种不同布局的cell
    2. 根据数据中特定的字段来判断要显示的哪种cell
     3. 多种 Cell 的应用场景非常广
if ([godGirl.gender isEqualToString:@" " ]) {
        // 显示带图片的 cell
       
static NSString *identifiter = @"GodGirlCell" ; // 按照这个标示符 初始化这种 Cell 不要重复
       
GodGirlCell *cell = [tableView dequeueReusableCellWithIdentifier :identifiter];
       
if (cell == nil ) {
            cell = [[[
GodGirlCell alloc ] initWithStyle :( UITableViewCellStyleSubtitle ) reuseIdentifier :identifiter] autorelease ];
        }
       
// 显示数据
        cell.
model = godGirl;
       
return cell;
    }
else if ([godGirl. gender isEqualToString : @" " ]) {
       
// 显示 不带图片的 cell
       
static NSString *identifiter = @"GodBoyCell" ;
       
GodBoyCell *cell = [tableView dequeueReusableCellWithIdentifier :identifiter];
       
if (cell == nil ) {
            cell = [[[
GodBoyCell alloc ] initWithStyle :( UITableViewCellStyleSubtitle ) reuseIdentifier :identifiter] autorelease ];
        }

        cell.
model = godGirl;
       
       
return cell;
    }


二. Cell 的自适应高度

     1.
UILabel *label = [[ UILabel alloc ] initWithFrame : CGRectMake ( 30 , 100 , 300 , 100 )];
    label.
backgroundColor = [ UIColor grayColor ];
    [
self . window addSubview :label];
    label.
font = [ UIFont systemFontOfSize : 16 ];
   
NSString *string = @" 去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去 " ;
    label.
text = string;
    label.numberOfLines = 0;  
计算文字的高度
      该方法四个参数什么意思
     Size 是之前定义的 label 的宽度 高度给一个到达不了的大数
     NSStringDrawingUsesLineFragmentOrigin  按照文本的矩形区域 返回 高度
     构建一个字体大小的字典   字体大小的字号要跟定义 Label 的一样
     最后一个 nil

该方法计算 300   30 字号的 Label 的高度
    NSDictionary *dic = [ NSDictionary dictionaryWithObject :[ UIFont systemFontOfSize : 16 ] forKey : NSFontAttributeName ];
   
CGRect frame = [string boundingRectWithSize : CGSizeMake ( 300 , 100000 ) options :( NSStringDrawingUsesLineFragmentOrigin ) attributes :dic context : nil ];
   
NSLog ( @"%f" , frame. size . height );
    [label
release ];
   
CGRect newFrame = label. frame ;
    newFrame.
size . height = frame. size . height ;
    label.frame = newFrame;

     2.
NewsCell.m
- ( void )dealloc
{
    [
_titleLabel release ];
    [
_summaryLabel release ];
    [
_model release ];
    [
_myImageView release ];
    [
super dealloc ];
}
- ( void )setModel:( NewsModel *)model
{
   
if ( _model != model) {
        [
_model release ];
       
_model = [model retain ];
    }
   
self . titleLabel . text = model. title ;
   
self . summaryLabel . text = model. summary ;
   
// 初始化的时候都走这里
   
// 防止 cell 被复用后状态消失
   
// 不过是创建出来的 还是按照 model 中状态标识 来选取需要的图片
   
if (model. isSelect == YES ) {
       
self . myImageView . image = [ UIImage imageNamed : @"select" ];
    }
else {
       
self . myImageView . image = [ UIImage imageNamed : @"cancel" ];
    }
   
CGRect newFrame = self . summaryLabel . frame ;
    newFrame.
size . height = [ NewsCell cellWithModel :model];
   
self . summaryLabel . frame = newFrame;
}

- (
instancetype )initWithStyle:( UITableViewCellStyle )style reuseIdentifier:( NSString *)reuseIdentifier
{
   
self = [ super initWithStyle :style reuseIdentifier :reuseIdentifier];
   
if ( self ) {
        [
self addSubViews ];
    }
   
return self ;
}
- (
void )addSubViews
{
   
self . titleLabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 10 , 10 , 330 , 40 )];
   
self . titleLabel . backgroundColor = [ UIColor redColor ];
   
self . titleLabel . numberOfLines = 0 ;
   
self . titleLabel . font = [ UIFont systemFontOfSize : 16 ];
    [
self . contentView addSubview : self . titleLabel ];
    [
_titleLabel release ];
   
   
// 写一个 imageView
   
self . myImageView = [[ UIImageView alloc ] initWithFrame : CGRectMake ( 350 , 10 , 20 , 20 )];
   
self . myImageView . image = [ UIImage imageNamed : @"cancel" ];
    [
self . contentView addSubview : self . myImageView ];
    [
_myImageView release ];
   
   
self . summaryLabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 10 , 20 + self . titleLabel . frame . size . height , 350 , 130 )];
   
self . summaryLabel . numberOfLines = 0 ;
   
self . summaryLabel . font = [ UIFont systemFontOfSize : 16 ];
   
self . summaryLabel . backgroundColor = [ UIColor grayColor ];
    [
self . contentView addSubview : self . summaryLabel ];
    [
_summaryLabel release ];
}

// 通过一个字符串 返回一个高度

+ (
CGFloat )cellWithModel:( NewsModel *)model
{
   
// 计算字符串的高度
   
NSString *string = model. summary ;
   
NSDictionary *dic =[ NSDictionary dictionaryWithObject :[ UIFont systemFontOfSize : 16 ] forKey : NSFontAttributeName ];
   
CGRect frame = [string boundingRectWithSize : CGSizeMake ( 350 , 1000000 ) options :( NSStringDrawingUsesLineFragmentOrigin ) attributes :dic context : nil ];
    return frame.size.height;
}

NewsModel.m 
- ( void )dealloc
{
    [
_title release ];
    [
_summary release ];
    [
super dealloc ];
}
// 防崩赋值方法
- (
void )setValue:( id )value forUndefinedKey:( NSString *)key
{
   

RootViewController.m
// 数据准备
- (
void )setUpData
{
   
NSString *path = [[ NSBundle mainBundle ] pathForResource : @"NewsData" ofType : @"plist" ];
   
NSDictionary *plistDic = [ NSDictionary dictionaryWithContentsOfFile :path];
   
NSArray *newsArray = [plistDic objectForKey : @"news" ];
   
// 数组一定要初始化
   
self . dataArray = [ NSMutableArray array ];
   
for ( NSDictionary *dic in newsArray) {
       
NewsModel *model = [[ NewsModel alloc ] init ];
        model.
isSelect = NO ;
        [model
setValuesForKeysWithDictionary :dic];
        [
self . dataArray addObject :model];
       
        [model
release ];
    }
   
NSLog ( @"%@" , self . dataArray );
}

- (
void )addTableView
{
   
UITableView *tableView = [[ UITableView alloc ] initWithFrame :[ UIScreen mainScreen ]. bounds   style :( UITableViewStylePlain )];
    tableView.
delegate = self ;
    tableView.
dataSource = self ;
    [
self . view addSubview :tableView];
    [tableView
release ];
}
- (
NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
{
   
return self . dataArray . count ;
}


- (
UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
   
static NSString *identifiter = @"cell" ;
   
NewsCell *cell = [tableView dequeueReusableCellWithIdentifier :identifiter];
   
if (cell == nil ) {
        cell = [[
NewsCell alloc ] initWithStyle :( UITableViewCellStyleSubtitle ) reuseIdentifier :identifiter];
    }
   
NewsModel *model = [ self . dataArray objectAtIndex :indexPath. row ];
    cell.
model = model;
   
return cell;
}


- (
CGFloat )tableView:( UITableView *)tableView heightForRowAtIndexPath:( NSIndexPath *)indexPath
{
   
// 取出 model 调用 cellWithModel 方法得到高度
   
NewsModel *model = [ self . dataArray objectAtIndex :indexPath. row ];
   
CGFloat SummaryHeight = [ NewsCell cellWithModel :model];
   
return 20 + 20 + 40 + SummaryHeight + 20 ;
}

// 点击触发的方法
- (
void )tableView:( UITableView *)tableView didSelectRowAtIndexPath:( NSIndexPath *)indexPath
{
   
// 获取要点击的 Cell
   
// 下面方法是获取自定义 cell 的方法
   
NewsCell *cell = ( NewsCell *)[tableView cellForRowAtIndexPath :indexPath];
   
// 不是自定义方法 就如下写
   
//UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
   
NewsModel *model = [ self . dataArray objectAtIndex :indexPath. row ];
   
// 通过 model 的状态 更改图片
   
// 改变 model 的状态
    model.
isSelect = !model. isSelect ;
   
if (model. isSelect == YES ) {
        cell.
myImageView . image = [ UIImage imageNamed : @"select" ];
    }
else {
        cell.
myImageView . image = [ UIImage imageNamed : @"cancel" ];
    }
   
NSLog ( @"%d" , model. isSelect );
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值