使用代码创建UITableViewCell

先看一下,我们将要做出的效果:

</pre><p></p><p>如上图中,现在分析:</p><p>1,这像是一个表格,而表格的每一个cell高度不定。</p><p>2,头像不一样</p><p>3,昵称不一样,昵称的字数也不一样</p><p>4,有的有会员图标(昵称显示红色),有的没有(昵称显示黑色),</p><p>5,内容不一样,内容的高度不定</p><p>6,有的有配图,有的没有配图</p><p>如果使用xib创建,那么cell的高度无法确定,控件的位置无法确定,所以,我们采用,整个表格使用一个UITableViewController, 里边的cell采用代码创建。数据使用加载plist文件的方式。</p><p>先看一下我们的plist文件:</p><p><img src="https://img-blog.csdn.net/20140831175442688?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWRhZGFkYWRhZGFkYWQ0MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" /></p><p>一:文件分类及作用:</p><p><img src="https://img-blog.csdn.net/20140831175555859?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWRhZGFkYWRhZGFkYWQ0MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" /></p><p>1,视图文件:StatusCell,  对应的是表格中的cell  。 也就是表格在加载UITableViewCell的时候,我们要用代码创建出来。</p><p>2,模型文件:有两个Status 和 StatusFrame,</p><p>第一个是Status,  用于提供数据,例如,昵称,图片的名称,内容,等等。</p><p>第二个是StatusFrame, 用于提供cell中的各个控件的frame, 比如,图片大小及位置,内容的大小及位置,等等。</p><p>3,控制器:ViewController</p><p>这个ViewController继承自UITableViewController, 这样就拥有了UITableView的各个属性。</p><p>还有一点,我们的storyboard文件中,我们直接拖一个UITableView即可,同时,在属性设置框中将它的Custom Class  设置为ViewController 。</p><p>二:各个文件的代码:</p><p>1,ViewController.m文件中的代码:</p><p></p><p style="margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; font:normal normal normal 14px/normal Menlo"></p><p style="margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; font:normal normal normal 14px/normal Menlo"></p><pre name="code" class="objc" style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; background-color: rgb(240, 240, 240); ">#import "MJViewController.h"
#import "MJStatus.h"
#import "MJStatusCell.h"
#import "MJStatusFrame.h"

@interface MJViewController ()

@property(nonatomic,strong)NSArray *statusFrames;

@end

@implementation MJViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
}
/** 懒加载(只加载一次) */
-(NSArray *)statusFrames{
    
    if(_statusFrames == nil){
        NSString *path = [[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
        NSMutableArray *statusFrameArray = [NSMutableArray array];
        for (NSDictionary *dict in dictArray) {
            MJStatus *status = [MJStatus statusWithDict:dict];
            MJStatusFrame *statusFrame = [[MJStatusFrame alloc] init];
            statusFrame.status = status;
            
            [statusFrameArray addObject:statusFrame];
        }
        _statusFrames = statusFrameArray;
    }
    return _statusFrames;
}
#pragma mark - UITableView的数据源方法
/** 返回本组数据有多少行 */
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.statusFrames.count;
}
#pragma mark 返回每一组的UITableViewcell
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 1,创建cell
    MJStatusCell *cell = [MJStatusCell cellWithTableView:tableView];
    
    // 2,设置cell的数据和控件的frame
    cell.statusFrame = self.statusFrames[indexPath.row];
    
    return cell;
  
}

/** 每一行的高度 */
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    MJStatusFrame *statusFrame = self.statusFrames[indexPath.row];
    
    return statusFrame.cellHeight;
    
}

@end


2,StatusCell.h中的代码:

#import <UIKit/UIKit.h>
@class MJStatusFrame;
@interface MJStatusCell : UITableViewCell
@property(nonatomic,strong) MJStatusFrame *statusFrame;

+(id)cellWithTableView:(UITableView *)tableView;

@end

StatusCell.m中的代码:

#import "MJStatusCell.h"
#import "MJStatus.h"
#import "MJStatusFrame.h"

#define MJNameFont [UIFont systemFontOfSize:13]
#define MJTextFont [UIFont systemFontOfSize:12]
@interface MJStatusCell ()
/** 
 头像 
*/
@property(nonatomic,weak) UIImageView *iconImgView;
/** 昵称 */
@property(nonatomic,weak) UILabel *nameLbl;
/** 会员图标 */
@property(nonatomic,weak) UIImageView *vipImgView;
/** 正文 */
@property(nonatomic,weak) UILabel *textLbl;
/** 配图 */
@property(nonatomic,weak) UIImageView *pictureImgView;

@end


@implementation MJStatusCell

+(id)cellWithTableView:(UITableView *)tableView{
    static NSString *flag = @"status";
    
    MJStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:flag];
    
    if(cell == nil){
        cell = [[MJStatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:flag];
    }
    return cell;
}

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        
        //头像
        UIImageView *iconImgView = [[UIImageView alloc] init];
        [self.contentView addSubview:iconImgView];
        self.iconImgView = iconImgView;
        
        //昵称
        UILabel *nameLbl = [[UILabel alloc] init];
        nameLbl.font = MJNameFont;
        [self.contentView addSubview:nameLbl];
        self.nameLbl = nameLbl;
        
        //会员头像
        UIImageView *vipImgView = [[UIImageView alloc] init];
        vipImgView.image = [UIImage imageNamed:@"vip"];
        [self.contentView addSubview:vipImgView];
        self.vipImgView = vipImgView;
        
        //正文
        UILabel *textLbl = [[UILabel alloc] init];
        textLbl.numberOfLines = 0;
        textLbl.font = MJTextFont;
        [self.contentView addSubview:textLbl];
        self.textLbl = textLbl;
        
        //配图
        UIImageView *pictureImgView = [[UIImageView alloc] init];
        [self.contentView addSubview:pictureImgView];
        self.pictureImgView = pictureImgView;
        
    }
    return self;
}

-(void)setStatusFrame:(MJStatusFrame *)statusFrame{
    _statusFrame = statusFrame;
    //1,设置数据
    [self settingData];
    //2,设置frame
    [self settingFrame];
}
/**
 设置数据
 */
-(void)settingData{
    /** 头像 */
    self.iconImgView.image = [UIImage imageNamed:self.statusFrame.status.icon];
    /** 昵称 */
    self.nameLbl.text = self.statusFrame.status.name;
    /** 会员头像 */
    if(self.statusFrame.status.vip){
        self.vipImgView.hidden = NO;
        self.nameLbl.textColor = [UIColor redColor];
    }else{
        self.vipImgView.hidden = YES;
        self.nameLbl.textColor = [UIColor blackColor];
    }
    /** 正文 */
    self.textLbl.text = self.statusFrame.status.text;
    /** 配图 */
    if(self.statusFrame.status.picture){
        self.pictureImgView.hidden = NO;
        self.pictureImgView.image = [UIImage imageNamed:self.statusFrame.status.picture];
    }else{
        self.pictureImgView.hidden = YES;
    }
    
}
/**
 设置frame
 */
-(void)settingFrame{
    /** 头像 */
    
    self.iconImgView.frame = self.statusFrame.iconFrame;
    
    /** 昵称 */
    self.nameLbl.frame =self.statusFrame.nameFrame;
  
    /** 会员头像 */
    self.vipImgView.frame = self.statusFrame.vipFrame;
    
    /** 正文 */
    self.textLbl.frame = self.statusFrame.textFrame;
    
    /** 配图 */
    if(self.statusFrame.status.picture){
         self.pictureImgView.frame = self.statusFrame.pictureFrame;
    }
   
    
}

@end


3, status.h中的代码:

#import <Foundation/Foundation.h>

@interface MJStatus : NSObject
/** 正文 */
@property(nonatomic,copy) NSString *text;
/** 头像 */
@property(nonatomic,copy) NSString *icon;
/** 昵称 */
@property(nonatomic,copy) NSString *name;
/** 配图 */
@property(nonatomic,copy) NSString *picture;
/** 会员 */
@property(nonatomic,assign) BOOL vip;

+(id)statusWithDict:(NSDictionary *)dict;
-(id)initWithDict:(NSDictionary *)dict;

@end

Status.m中的代码:

#import "MJStatus.h"

@implementation MJStatus

+(id)statusWithDict:(NSDictionary *)dict{
    return [[self alloc] initWithDict:dict];
}
-(id)initWithDict:(NSDictionary *)dict{
    if(self = [super init]){
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

@end


4,StatusFrame.h文件中的代码:

#import <Foundation/Foundation.h>
@class MJStatus;

@interface MJStatusFrame : NSObject

@property(nonatomic,assign,readonly) CGRect iconFrame;
@property(nonatomic,assign,readonly) CGRect nameFrame;
@property(nonatomic,assign,readonly) CGRect vipFrame;
@property(nonatomic,assign,readonly) CGRect textFrame;
@property(nonatomic,assign,readonly) CGRect pictureFrame;

@property(nonatomic,assign,readonly) CGFloat cellHeight;

@property(nonatomic,strong) MJStatus *status;


@end

StatusFrame.m中的代码:

#import "MJStatusFrame.h"
#import "MJStatus.h"

#define MJNameFont [UIFont systemFontOfSize:13]
#define MJTextFont [UIFont systemFontOfSize:12]

@implementation MJStatusFrame

-(void)setStatus:(MJStatus *)status{
    _status = status;
    CGFloat padding = 10;
    
    CGFloat iconX = padding;
    CGFloat iconY = padding;
    CGFloat iconW = 30;
    CGFloat iconH = 30;
    
    _iconFrame = CGRectMake(iconX, iconY, iconW, iconH);
    
    /** 昵称 */
    CGFloat nameX = CGRectGetMaxX(_iconFrame) + padding;
    CGSize nameMaxSize = [self.status.name sizeWithFont:MJNameFont];
    CGFloat nameW = nameMaxSize.width;
    CGFloat nameH = nameMaxSize.height;
    CGFloat nameY = padding + (iconH - nameH) * 0.5;
    _nameFrame = CGRectMake(nameX, nameY, nameW, nameH);
    
    /** 会员头像 */
    
    CGFloat vipX = CGRectGetMaxX(_nameFrame) + padding;
    CGFloat vipY = nameY;
    CGFloat vipW = 14;
    CGFloat vipH = 14;
    
    _vipFrame = CGRectMake(vipX, vipY, vipW, vipH);
    
    /** 正文 */
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(_iconFrame) + padding;
    CGFloat textW = 300;
    CGSize textMaxSize = [self.status.text sizeWithFont:MJTextFont constrainedToSize:CGSizeMake(300, MAXFLOAT) lineBreakMode:UILineBreakModeCharacterWrap];
    CGFloat textH = textMaxSize.height;
    _textFrame = CGRectMake(textX, textY, textW, textH);
    
    /** 配图 */
    CGFloat pictureX = iconX;
    CGFloat pictureY = CGRectGetMaxY(_textFrame) + padding;
    CGFloat pictureW = 100;
    CGFloat pictureH = 100;
    _pictureFrame = CGRectMake(pictureX, pictureY, pictureW, pictureH);
    
    if(self.status.picture){
        _cellHeight = CGRectGetMaxY(_pictureFrame) + padding;
    }else{
        _cellHeight = CGRectGetMaxY(_textFrame) + padding;
    }
    
    
}

@end

虽然贴上了代码,还是要说一下这个过程:

1,在控制器初始化的时候,从plist文件中将数据提取出来,然后放到Status这个模型中,在创建一个StatusFrame模型,这个StatusFrame模型中有一个属性是Status, 而数组中放入的就是StatusFrame这个模型对象。 在赋值的时候,就把各个控件的frame 以 cell的高度计算了出来。

2,控制器初始化完以后,会先加载一共有多少组这个方法,-(NSInteger)numberOfSectionsInTableView:  ,

3,继续加载每组有多少行这个方法:-(NSInteger)tableView:numberOfRowsInSection:
4,继续加载 -(CGFloat)tableView:heightForRowAtIndexPath: 这个方法,这个方法主要是返回表格中,每一行的高度,这时候,我们就可以从已经加载完的数组将cell的高度提取出来了。

5,加载完每一组高度这个方法之后,会继续加载 -(UITableViewCell *)tableView:cellForRowAtIndexPath: 这个方法是返回每一行的cell.  这段代码被调用的频率非常高,不用在这段代码中频繁创建cell,这样效率会有点低。现在粘上此段代码:

    // 1,创建cell

    MJStatusCell *cell = [MJStatusCell cellWithTableView:tableView];

    

    // 2,设置cell的数据和控件的frame

    cell.statusFrame = self.statusFrames[indexPath.row];

    

    return cell;

a,第一行代码,就是创建一个cell,创建cell代码如下:

+(id)cellWithTableView:(UITableView *)tableView{

    static NSString *flag = @"status";

    

    MJStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:flag];

    

    if(cell == nil){

        cell = [[MJStatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:flag];

    }

    return cell;

}

这段代码是采用,先从缓存池中去查找,是否有被先前不用的cell ,如果没有,就去创建一个cell,如果有cell,直接返回cell,如果没有cell,就直接创建一个cell。当然,在创建cell的时候,我们会创建这个cell中的子控件。

b,再看   cell.statusFrame = self.statusFrames[indexPath.row]; 这行代码,这行代码是将存在数组中的模型对象数据提取出来,赋值给cell的frame对象,在赋值的时候,我们会设置cell控件中的数据和空间的frame.

现在贴上赋值的代码:

-(void)setStatusFrame:(MJStatusFrame *)statusFrame{

    _statusFrame = statusFrame;

    //1,设置数据

    [self settingData];

    //2,设置frame

    [self settingFrame];

}

/**

 设置数据

 */

-(void)settingData{

    /** 头像 */

    self.iconImgView.image = [UIImage imageNamed:self.statusFrame.status.icon];

    /** 昵称 */

    self.nameLbl.text = self.statusFrame.status.name;

    /** 会员头像 */

    if(self.statusFrame.status.vip){

        self.vipImgView.hidden = NO;

        self.nameLbl.textColor = [UIColor redColor];

    }else{

        self.vipImgView.hidden = YES;

        self.nameLbl.textColor = [UIColor blackColor];

    }

    /** 正文 */

    self.textLbl.text = self.statusFrame.status.text;

    /** 配图 */

    if(self.statusFrame.status.picture){

        self.pictureImgView.hidden = NO;

        self.pictureImgView.image = [UIImage imageNamed:self.statusFrame.status.picture];

    }else{

        self.pictureImgView.hidden = YES;

    }

    

}

/**

 设置frame

 */

-(void)settingFrame{

    /** 头像 */

    

    self.iconImgView.frame = self.statusFrame.iconFrame;

    

    /** 昵称 */

    self.nameLbl.frame =self.statusFrame.nameFrame;

  

    /** 会员头像 */

    self.vipImgView.frame = self.statusFrame.vipFrame;

    

    /** 正文 */

    self.textLbl.frame = self.statusFrame.textFrame;

    

    /** 配图 */

    if(self.statusFrame.status.picture){

         self.pictureImgView.frame = self.statusFrame.pictureFrame;

    }

   

    

}


通过代码自定义cell(cell的高度不一致)

总结:

1,新建一个继承自UITableViewCell类。

2,重新这个类的initWithStyle:reuseIdentifier:方法

  a,添加所有需要显示的子控件(不需要设置子控件的数据和frame,子控件要添加到contentView中)

  b,进行子控件的一次性的属性设置(有些属性只需要设置一次,比如,字体,固定的图片等)

3,提供2个模型

  a,数据模型:存放文字数据\图片数据

  b,frame模型:存放数据模型,以及所有子控件的frame,以及cell的高度

4,cell拥有一个frame模型(不要直接拥有数据模型)

5,重写frame模型属性的setter方法:在这个方法中设置子控件的显示数据和frame

6, frame模型数据的初始化采用懒加载的方式(每一个cell对应的frame模型数据只加载一次)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值