iOS開發之自定義UITableViewCell

等高的Cell緩存

1、storyboard方式佈局

  1. 建立一個繼承自UITableViewCell的子類字體

  2. 在storyboard中atom

    - 往cell裏面增長鬚要用到的子控件spa

        

      - 設置cell的重用標識code

        

     - 設置cell的class爲我剛纔建立的那個Cell類型XXDealCellorm

    

    3. 在控制器中繼承

      - 利用重用標識找到cellstring

      - 給cell傳遞模型數據it

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.deals.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *ID = @"deal";
    
    XXDealCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    //取出模型數據
    cell.deal = self.deals[indexPath.row];
    
    return cell;
}

     

    4.在XXDealCell中,將storyboard中的子控件連線到類擴展中,而且提供一個模型屬性,重寫模型的set方法,在這個方法中設置模型數據到子控件上。

//
//  XXDealCell.m
//  自定義等高的cell
//
//  Created by Daniel on 16/3/17.
//  Copyright © 2016年 Daniel. All rights reserved.
//

#import "XXDealCell.h"
#import "XXDeal.h"

@interface XXDealCell()

@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *titleLable;
@property (weak, nonatomic) IBOutlet UILabel *priceLable;
@property (weak, nonatomic) IBOutlet UILabel *buyCountLable;


@end

@implementation XXDealCell

- (void)setDeal:(XXDeal *)deal {
    
    _deal = deal;  
    //設置數據
    self.iconView.image = [UIImage imageNamed:deal.icon];
    self.titleLable.text = deal.title;
    self.priceLable.text = [NSString stringWithFormat:@"¥%@", deal.price]; 
    self.buyCountLable.text = [NSString stringWithFormat:@"%@人已購買", deal.buyCount];
    
}

@end



2、xib方式

1.建立一個繼承自UITableViewCell的子類,好比XXDealCell

2.建立一個xib文件(文件名建議跟cell的類名同樣),好比XXDealCell.xib,拖拽一個UITableViewCell出來,修改cell的class爲XXDealCell,設置cell的重用標識,往cell中添加須要用到的子控件

這兩步和storyboard方式都是大同小異。

3.在控制器中,利用registerNib...方法註冊xib文件,利用重用標識找到cell(若是沒有註冊xib文件,就須要手動去加載xib文件),給cell傳遞模型數據。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XXDealCell class]) bundle:nil] forCellReuseIdentifier:@"deal"];
    
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *ID = @"deal";
    
    XXDealCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    //若是不註冊,就要這樣手動加載xib
//    if(cell == nil) {
//        cell = [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([XXDealCell class]) owner:nil options:nil]lastObject];
//    }
    
    //取出模型數據
    cell.deal = self.deals[indexPath.row];

    
    return cell;
}

4.在XXDealCell中,將xib中的子控件連線到類擴展中,須要提供一個模型屬性,重寫模型的set方法,在這個方法中設置模型數據到子控件上,也能夠將建立得到cell的代碼封裝起來(好比cellWithTableView:方法)

//
//  XXDealCell.m
//  自定義等高的cell
//
//  Created by Daniel on 16/3/17.
//  Copyright © 2016年 Daniel. All rights reserved.
//

#import "XXDealCell.h"
#import "XXDeal.h"

@interface XXDealCell()

@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *titleLable;
@property (weak, nonatomic) IBOutlet UILabel *priceLable;
@property (weak, nonatomic) IBOutlet UILabel *buyCountLable;


@end

@implementation XXDealCell

- (void)setDeal:(XXDeal *)deal {
    
    _deal = deal;
    
    //設置數據
    self.iconView.image = [UIImage imageNamed:deal.icon];
    
    self.titleLable.text = deal.title;
    
    self.priceLable.text = [NSString stringWithFormat:@"¥%@", deal.price];
    
    self.buyCountLable.text = [NSString stringWithFormat:@"%@人已購買", deal.buyCount];
    
    
}

+ (instancetype)cellWithTableView:(UITableView *) tableView {
    
    static NSString *ID = @"deal";
    
    XXDealCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    if(cell == nil) {
        cell = [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([XXDealCell class]) owner:nil options:nil]lastObject];
    }
    
    return cell;
    
}

@end
- (void)viewDidLoad {
    [super viewDidLoad];
    
//    [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XXDealCell class]) bundle:nil] forCellReuseIdentifier:@"deal"];
    
}



#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.deals.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    XXDealCell *cell = [XXDealCell cellWithTableView:tableView];
    
    //取出模型數據
    cell.deal = self.deals[indexPath.row];

    
    return cell;
}



3、代碼方式

-------------使用frame

1.建立一個繼承自UITableViewCell的子類,好比XXDealCell

- 在initWithStyle:reuseIdentifier:方法中添加子控件,設置子控件的初始化屬性(好比文字顏色、字體)等

- 在layoutSubviews方法中設置子控件的frame

- 須要提供一個模型屬性,重寫模型的setter方法,在這個方法中設置模型數據到子控件

//一、在initWithStyle:reuseIdentifier:方法中添加子控件
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if(self == [super initWithStyle:style reuseIdentifier:reuseIdentifier ]) {
        
        UIImageView *iconView = [[UIImageView alloc]init];
        [self.contentView addSubview:iconView];
        self.iconView = iconView;
        
        UILabel *titleLable = [[UILabel alloc]init];
        [self.contentView addSubview:titleLable];
        self.titleLable = titleLable;
        
        UILabel *priceLable = [[UILabel alloc]init];
        [self.contentView addSubview:priceLable];
        priceLable.textColor = [UIColor orangeColor];
        self.priceLable = priceLable;

        
        UILabel *buyCountLable = [[UILabel alloc]init];
        [self.contentView addSubview:buyCountLable];
        buyCountLable.textAlignment = NSTextAlignmentRight;
        buyCountLable.font = [UIFont systemFontOfSize:11];
        buyCountLable.textColor = [UIColor lightGrayColor];
        self.buyCountLable = buyCountLable;

    }
    return self;
}

//二、在layoutSubviews方法中設置子控件的frame
- (void)layoutSubviews {
    
    [super layoutSubviews];
    
    //iconView
    CGFloat iconX = 10;
    CGFloat iconY = 10;
    CGFloat iconW = 100;
    CGFloat iconH = self.contentView.frame.size.height - 2 * iconY;
    self.iconView.frame = CGRectMake(iconX, iconY, iconW, iconH);
    
    //titleLable
    CGFloat titleX = CGRectGetMaxX(self.iconView.frame) + 10;
    CGFloat titleY = iconY;
    CGFloat titleW = self.contentView.frame.size.width - titleX - 10;
    CGFloat titleH = 20;
    self.titleLable.frame = CGRectMake(titleX, titleY, titleW, titleH);
    
    //priceView
    CGFloat priceX = titleX;
    CGFloat priceH = 20;
    CGFloat priceY = self.contentView.frame.size.height - priceH - 10;
    CGFloat priceW = 70;
    self.priceLable.frame = CGRectMake(priceX, priceY, priceW, priceH);
    
    //buyCountView
    CGFloat buyH = priceH;
    CGFloat buyY = self.contentView.frame.size.height - 10 - buyH;
    CGFloat buyX = priceX + priceW + 10;
    CGFloat buyW = self.contentView.frame.size.width - buyX - 10;
    
    self.buyCountLable.frame = CGRectMake(buyX, buyY, buyW, buyH);

    
}


//三、重寫模型的setter方法
- (void)setDeal:(XXDeal *)deal {
    
    _deal = deal;
    
    //設置數據
    self.iconView.image = [UIImage imageNamed:deal.icon];
    
    self.titleLable.text = deal.title;
    
    self.priceLable.text = [NSString stringWithFormat:@"¥%@", deal.price];
    
    self.buyCountLable.text = [NSString stringWithFormat:@"%@人已購買", deal.buyCount];
    
    
}

2.在控制器中,利用registerClass...方法註冊XMGDealCell類,利用重用標識找到cell(若是沒有註冊類,就須要手動建立cell,給cell傳遞模型數據,也能夠將建立得到cell的代碼封裝起來(好比cellWithTableView:方法)。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    XXDealCell *cell = [XXDealCell cellWithTableView:tableView];
    //取出模型數據
    cell.deal = self.deals[indexPath.row];
    return cell;
}


---------------------使用autoLayout

與使用frame不一樣的是:在initWithStyle:reuseIdentifier:方法中添加子控件後直接添加約束,而後不須要layoutSubviews方法了。其餘都是同樣的,添加約束使用Masonry。

//一、在initWithStyle:reuseIdentifier:方法中添加子控件
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if(self == [super initWithStyle:style reuseIdentifier:reuseIdentifier ]) {
        
        CGFloat margin = 10;
        
        UIImageView *iconView = [[UIImageView alloc]init];
        [self.contentView addSubview:iconView];
        self.iconView = iconView;
        [iconView makeConstraints:^(MASConstraintMaker *make) {
            make.width.equalTo(100);
            make.left.top.equalTo(self.contentView).offset(margin);
            make.bottom.equalTo(self.contentView).offset(-margin);
        }];
        
        UILabel *titleLable = [[UILabel alloc]init];
        [self.contentView addSubview:titleLable];
        self.titleLable = titleLable;
        [titleLable makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(iconView.right).offset(margin);
            make.top.equalTo(iconView);
            make.right.equalTo(self.contentView).offset(-margin);
        }];
        
        UILabel *priceLable = [[UILabel alloc]init];
        [self.contentView addSubview:priceLable];
        priceLable.textColor = [UIColor orangeColor];
        self.priceLable = priceLable;
        [priceLable makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(titleLable);
            make.bottom.equalTo(iconView);
        }];
        
        UILabel *buyCountLable = [[UILabel alloc]init];
        [self.contentView addSubview:buyCountLable];
        buyCountLable.textAlignment = NSTextAlignmentRight;
        buyCountLable.font = [UIFont systemFontOfSize:11];
        buyCountLable.textColor = [UIColor lightGrayColor];
        self.buyCountLable = buyCountLable;
        [buyCountLable makeConstraints:^(MASConstraintMaker *make) {
            make.bottom.equalTo(priceLable);
            make.right.equalTo(self.contentView).offset(-margin);
            make.left.equalTo(priceLable).offset(margin);
        }];

    }
    return self;
}



非等高cell

  1. xib自定義非等高cell

- 在模型中增長一個cellHeight屬性,用來存放對應cell的高度

/**
 *  cell的高度
 */
@property(assign, nonatomic)CGFloat cellHeight;

- 在cell的模型屬性setter方法中調用[self layoutIfNeed]方法強制佈局,而後計算出模型的cellheight屬性值

//強制佈局
[self layoutIfNeeded];

- 在控制器中實現tableView:estimatedHeightForRowAtIndexPath:方法,返回一個估計高度

/**
 *  返回每個cell的估計高度
 *
 *  @param tableView
 *  @param indexPath
 *
 *  @return 只要返回了估計高度,tableView就會先調用tableView:cellForRowAtIndexPath:方法建立cell
 *          再調用tableView:heightForRowAtIndexPath:方法獲取cell的真實高度
 */
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 100;
}

- 在控制器中實現tableView:heightForRowAtIndexPath:方法,返回cell的真實高度(模型中的cellHeight屬性)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    XXStatusCell *cell = [XXStatusCell cellWithTableView:tableView];
    
    //設置數據
    cell.status = self.statuses[indexPath.row];
    
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    XXStatus *status = self.statuses[indexPath.row];
    return status.cellHeight;
}

二、storyboard方式自定義非等高cell

用storyboard和xib其實大同小異,直接在storyboard中添加子控件並添加約束,設置重用標識,修改cell的類,修改cell爲動態建立類型。注意,若是Lable要顯示多行的話,Lines要改成0,並且cell高度極端準確,要加一個方法:

- (void)awakeFromNib {
    self.contentLable.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
}

而後獲取cell時直接在緩存池中根據重用標識去查找,其餘的和xib方式同樣。

+ (instancetype)cellWithTableView :(UITableView *)tableView {
    
    return [tableView dequeueReusableCellWithIdentifier:@"status"];
    
}
相關文章
相關標籤/搜索