UI 一一 自定义不等高cell (storyboard方式)

通过storyboard方式来自定义不等高cell


  • 添加子控件和contentView之间的间距约束


  • 设置tableViewCell的真实行高和估算行高
// 告诉tableView所有cell的真实高度是自动计算(根据设置的约束来计算)
self.tableView.rowHeight = UITableViewAutomaticDimension;
// 告诉tableView所有cell的估算高度
self.tableView.estimatedRowHeight = 44;


这种self-sizing技术,只支持从iOS8以后版本.

代码如下:

ZYStatus文件

#import <UIKit/UIKit.h>

// 模型数据
@interface ZYStatus : NSObject

/** 图像 */
@property (nonatomic, copy) NSString *icon;

/** 昵称 */
@property (nonatomic, copy) NSString *name;

/** 正文(内容) */
@property (nonatomic, copy) NSString *text;

/** VIP */
@property (nonatomic, assign, getter=isVip) BOOL vip;

/** 配图 */
@property (nonatomic, copy) NSString *picture;

@end

@implementation ZYStatus

@end


ZYStatusCell文件

#import <UIKit/UIKit.h>
@class  ZYStatus;
@interface ZYStatusCell : UITableViewCell

/** 微博模型数据 */
@property(nonatomic,strong)ZYStatus *status;

@end

#import "ZYStatus.h"


@interface ZYStatusCell ()

/** 图像 */
@property (nonatomic, weak)IBOutlet UIImageView *iconImageView;
/** 昵称 */
@property (nonatomic, weak)IBOutlet UILabel *nameLabel;
/** vip */
@property (nonatomic, weak)IBOutlet UIImageView *vipImageView;
/** 正文 */
@property (nonatomic, weak)IBOutlet UILabel *text_Label;
/** 配图 */
@property (nonatomic, weak)IBOutlet UIImageView *pictureImageView;

/** 图片的高度约束 */
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *pictureHeight;

/** 图片与cell底部的间距约束 */
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *pictureBottomSpace;

@end

@implementation ZYStatusCell


3. 给子控件赋值
- (void)setStatus:(ZYStatus *)status
{
    _status = status;
    // 赋值
    self.iconImageView.image = [UIImage imageNamed:status.icon];
    self.nameLabel.text = status.name;
    
    if (status.isVip) {
        self.vipImageView.hidden = NO;
        // 有if就有else,如果在这里写字体颜色,会出现数据紊乱,不是会员的用户的名称也是黄色
        self.nameLabel.textColor = [UIColor orangeColor];
        self.vipImageView.image = [UIImage imageNamed:@"vip"];
    }else{
        self.vipImageView.hidden = YES;
        self.nameLabel.textColor = [UIColor blackColor];
    }
    
    self.text_Label.text = status.text;
    
    if (status.picture) {
        self.pictureImageView.hidden = NO;
        self.pictureImageView.image = [UIImage imageNamed:status.picture];
        // 因为有配图的cell,要设置配图的高度
        self.pictureHeight.constant = 100;
        self.pictureBottomSpace.constant = 10;
    }else{
        self.pictureImageView.hidden = YES;
        // 如果没有配图的cell,要把配图高度约束设为0
        self.pictureHeight.constant = 0;
        self.pictureBottomSpace.constant = 0;
        
    }
    
}


@end


Main.storyboard文件




ViewController文件

#import "ViewController.h"
#import "MJExtension.h"
#import "ZYStatusCell.h"
#import "ZYStatus.h"

@interface ViewController ()

/** 所有的微博 */
@property (nonatomic,strong) NSArray *statuses;

@end

@implementation ViewController

- (NSArray *)statuses
{
    if (_statuses == nil) {
        //加载plist中的数据到,模型ZYStatus中
        _statuses = [ZYStatus mj_objectArrayWithFilename:@"statuses.plist"];
    }
    
    return _statuses;
}



- (void)viewDidLoad {
    [super viewDidLoad];
    
    // self-sizing技术,只适合ios8以上版本
    // 告诉tableView所有cell的真实高度是自动计算的(根据设置的约束来计算)
    self.tableView.rowHeight = UITableViewAutomaticDimension;
    
    // 告诉tableView所有cell的估算高度
    self.tableView.estimatedRowHeight = 44;
    
}

#pragma -mark 数据源方法

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID = @"status";
    
    // 到缓存池中查看是否有可循环利用的cell
    ZYStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    // 传递模型数据
    cell.status = self.statuses[indexPath.row];
    
    return cell;
}



@end




如果要支持iOS8之前

  • 如果cell内部有自动换行的label,需要设置preferredMaxLayoutWidth属性
- (void)awakeFromNib
{
    // 手动设置文字的最大宽度(目的是:让label知道自己文字的最大宽度,进而能够计算出自己的frame)
    self.text_label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
}

  • 设置tableView的cell估算高度
// 告诉tableView所有cell的估算高度(设置了估算高度,就可以减少tableView:heightForRowAtIndexPath:方法的调用次数)
self.tableView.estimatedRowHeight = 200;

  • 在代理方法中计算cell的高度
ZYStatusCell *cell;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 创建一个临时的cell(cell的作用:根据模型数据布局所有的子控件,进而计算出cell的高度)
    if (!cell) {
        cell = [tableView dequeueReusableCellWithIdentifier:ID];
    }

    // 设置模型数据
    cell.status = self.statuses[indexPath.row];

    return cell.height;
}

具体代码如下:

注意: 首先要取消storyboard中与contentView底部的间距


ZYStatus文件

// 模型数据
@interface ZYStatus : NSObject

/** 图像 */
@property (nonatomic, copy) NSString *icon;

/** 昵称 */
@property (nonatomic, copy) NSString *name;

/** 正文(内容) */
@property (nonatomic, copy) NSString *text;

/** VIP */
@property (nonatomic, assign, getter=isVip) BOOL vip;

/** 配图 */
@property (nonatomic, copy) NSString *picture;

@end


@implementation ZYStatus



@end

ZYStatusCell文件

#import <UIKit/UIKit.h>
@class  ZYStatus;
@interface ZYStatusCell : UITableViewCell


/** 微博模型数据 */
@property(nonatomic,strong)ZYStatus *status;

- (CGFloat)cellHeight;

@end

#import "ZYStatus.h"


@interface ZYStatusCell ()

/** 图像 */
@property (nonatomic, weak)IBOutlet UIImageView *iconImageView;
/** 昵称 */
@property (nonatomic, weak)IBOutlet UILabel *nameLabel;
/** vip */
@property (nonatomic, weak)IBOutlet UIImageView *vipImageView;
/** 正文 */
@property (nonatomic, weak)IBOutlet UILabel *text_Label;
/** 配图 */
@property (nonatomic, weak)IBOutlet UIImageView *pictureImageView;

@end

@implementation ZYStatusCell


3. 给子控件赋值
- (void)setStatus:(ZYStatus *)status
{
    _status = status;
    // 赋值
    self.iconImageView.image = [UIImage imageNamed:status.icon];
    self.nameLabel.text = status.name;
    
    if (status.isVip) {
        self.vipImageView.hidden = NO;
        // 有if就有else,如果在这里写字体颜色,会出现数据紊乱,不是会员的用户的名称也是黄色
        self.nameLabel.textColor = [UIColor orangeColor];
        self.vipImageView.image = [UIImage imageNamed:@"vip"];
    }else{
        self.vipImageView.hidden = YES;
        self.nameLabel.textColor = [UIColor blackColor];
    }
    
    self.text_Label.text = status.text;
    
    if (status.picture) {
        self.pictureImageView.hidden = NO;
        self.pictureImageView.image = [UIImage imageNamed:status.picture];

    }else{
        self.pictureImageView.hidden = YES;
       
        
    }
    
}

// 这个方法只会调用一次
- (void)awakeFromNib
{
    // 手动设置文字的最大宽度(让label能够计算出自己最真实的尺寸)
    self.text_Label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
}

- (CGFloat)cellHeight
{
//    self.text_Label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
    
    [self layoutIfNeeded];
    
    CGFloat cellHeight = 0;
    if (self.status.picture) { //有配图
        cellHeight = CGRectGetMaxY(self.pictureImageView.frame) + 10;
    }else{  // 无配图
        cellHeight = CGRectGetMaxY(self.text_Label.frame) + 10;
    }
    return cellHeight;
}


@end

ViewController文件

#import "ViewController.h"
#import "MJExtension.h"
#import "ZYStatusCell.h"
#import "ZYStatus.h"

@interface ViewController ()

/** 所有的微博 */
@property (nonatomic,strong) NSArray *statuses;

@end

@implementation ViewController

- (NSArray *)statuses
{
    if (_statuses == nil) {
        //加载plist中的数据到,模型ZYStatus中
        _statuses = [ZYStatus mj_objectArrayWithFilename:@"statuses.plist"];
    }
    
    return _statuses;
}



- (void)viewDidLoad {
    [super viewDidLoad];
    
    // cell的估算高度(作用: 性能优化,减少heightForRowAtIndexPath方法的调用次数)
    // 假如一个cell的高度为100.iphone6的高度为650,所以会打印7次heightForRowAtIndexPath方法,来快速\
    估算有多少cell要显示
    self.tableView.estimatedRowHeight = 100;
    
}

#pragma -mark 数据源方法
NSString *ID = @"status";
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.statuses.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    // 到缓存池中查看是否有可循环利用的cell
    ZYStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    // 传递模型数据
    cell.status = self.statuses[indexPath.row];
    
    return cell;
}

ZYStatusCell *cell;
#pragma -mark 代理方法
// 系统之所以调用多次这个方法,为了计算contentSize的滚动范围,为了用户体验,计算滚动条的长度.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{

    if (cell == nil) {
        cell = [tableView dequeueReusableCellWithIdentifier:ID];
    }
    cell.status = self.statuses[indexPath.row];

    return cell.cellHeight;
    
}

@end





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

white camel

感谢支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值