iOS开发之有趣的UI —— 自定义不等高cell

这里写图片描述

一、静态cell和动态cell
一般比较固定的样式可通过storyboard中的静态cell或者动态cell进行操作,方便快捷高效。
静态cell创建方式
动态cell创建方式

二、纯代码是实现自定义不等高cell
下面通过案例来实现用纯代码的方式来完成自定义不等高cell的实现。

项目需求:
以微博为例,当别人发状态时,有的人发文字,有的人发文字和图片,那么如何实现这种方式呢?

项目思路:
在UITableViewCell中的系统样式中不能满足项目所需,那么我们首先得想,通过自定义cell的方式来完成,至于高度不等,那么我们可以在每一个cell中通过判断哪个控件是最后一个,然后就取它的高度然后和cell底部间留有间距就完成了。

项目实现过程:
1.创建项目,导入图片及plist文件
2.创建数据模型,用来进行plist字典数据转模型
3.创建一个继承自UITableViewCell的文件用来设置自定义cell以及数据的重写
4.在控制器中遵守UITableViewDataSourse协议,创建代理对象,实现代理方法等。

项目代码编码过程:
1.创建项目,导入图片及plist文件

2.创建ZJStatus数据模型
在ZJStatus.h中
/* 内容数据***********/
/* 头像 /
@property (nonatomic ,copy)NSString *icon;
/* 昵称 /
@property (nonatomic ,copy)NSString *name;
/* vip /
@property (nonatomic ,assign)BOOL vip;
/* 文字 /
@property (nonatomic ,copy)NSString *text;
/* 图片 /
@property (nonatomic ,copy)NSString *picture;

在ZJStatus.m中不做任何操作

(3)创建ZJStatusCell文件用来设置自定cell以及重写数据
在ZJStatusCell.h中
先导入@class ZJStatus;
将ZJStatus 所有属性进行声明
/* status的数据 /
@property (nonatomic,strong) ZJStatus *status;

在ZJStatusCell.m中

#import "ZJStatus.h"
#define KNameFont [UIFont systemFontOfSize:17]
#define KTextFont [UIFont systemFontOfSize:14]
@interface ZJStatusCell ()

// 声明一些属性
#import "ZJStatus.h"
#define KNameFont [UIFont 

// 定义宏 
systemFontOfSize:17]
#define KTextFont [UIFont systemFontOfSize:14]


@interface ZJStatusCell ()
/** 头像 */
@property (nonatomic ,weak)UIImageView *iconImageView;
/** 昵称 */
@property (nonatomic ,weak)UILabel *nameLabel;
/** vip */
@property (nonatomic ,weak)UIImageView * vipImageView;
/** 文字 */
@property (nonatomic ,weak)UILabel *TEXTLabel;
/** 图片 */
@property (nonatomic ,weak)UIImageView *pictureImageView;

@end
@implementation ZJStatusCell
/**
 *  添加子控件(把有可能显示的子控件都加进去)
 */
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

        // 1.昵称
        UIImageView *iconImageView = [[UIImageView alloc]init];
        [self.contentView addSubview:iconImageView];
        // 连线 建立关系
        self.iconImageView = iconImageView;

        // 2.标题
        UILabel *nameLabel = [[UILabel alloc]init];
        [self.contentView addSubview:nameLabel];
        self.nameLabel = nameLabel;
        // 设置文字大小
        self.nameLabel.font = KNameFont;
        // 连线 建立关系
        self.nameLabel = nameLabel;

        // 3.vip
        UIImageView *vipImageView = [[UIImageView alloc]init];
        vipImageView.image = [UIImage imageNamed:@"vip"];
        // 图片显示格式
        vipImageView.contentMode = UIViewContentModeCenter;
        [self.contentView addSubview:vipImageView];
        // 连线 建立关系
        self.vipImageView = vipImageView;

        // 4.文字
        UILabel *TEXTlabel = [[UILabel alloc]init];
        [self.contentView addSubview:TEXTlabel];
        self.TEXTLabel = TEXTlabel;
        // 设置文字大小
        self.TEXTLabel.font = KTextFont;
        // 连线 建立关系
        self.TEXTLabel = TEXTlabel;
        // 换行
        self.TEXTLabel.numberOfLines = 0;
        // 设置一个背景颜色
        self.TEXTLabel.backgroundColor = [UIColor redColor];

        // 5.配图
        UIImageView *pictureImageView = [[UIImageView alloc]init];
        [self.contentView addSubview:pictureImageView];
        self.pictureImageView = pictureImageView;
        // 连线 建立关系
        self.pictureImageView = pictureImageView;
    }

    return self;
}

// 布局子控件

- (void)layoutSubviews{
#warning 一定要调用 [super layoutSubviews];
    [super layoutSubviews];
    CGFloat margin = 10;
    // 1.设置头像的位置
    CGFloat iconX = margin;
    CGFloat iconY = margin;
    CGFloat iconW = 40;
    CGFloat iconH = iconW;
    self.iconImageView.frame = CGRectMake(iconX, iconY, iconW, iconH);

    // 2.设置标题位置
    CGFloat nameX = CGRectGetMaxX(self.iconImageView.frame) + margin;
    CGFloat nameY = iconY;
    // 计算文字所占据的尺寸
    NSDictionary *nameAttri = @{NSFontAttributeName :KNameFont
                               };
    CGSize nameSize = [self.status.name sizeWithAttributes:nameAttri];
    // 包装成结构体
    self.nameLabel.frame = (CGRect){{nameX,nameY},nameSize};

    // 3.设置vip图标
    if (self.status.vip) {
     CGFloat vipX = CGRectGetMaxX(self.nameLabel.frame) + margin;
     CGFloat vipY = nameY;
     CGFloat vipW = 14;
     CGFloat vipH = nameSize.height;
    self.vipImageView.frame = CGRectMake(vipX, vipY, vipW, vipH);
    }
    // 4.文字
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(self.iconImageView.frame) + margin;
    CGFloat textW = self.contentView.frame.size.width - iconX * 2;
    CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
    NSDictionary *textSize = @{NSFontAttributeName:KTextFont
                               };


    CGFloat textH = [self.status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;

    self.TEXTLabel.frame = CGRectMake(textX, textY, textW, textH);
    // 配图
    if (self.status.picture) {
        CGFloat pictureX = textX;
        CGFloat pictureY = CGRectGetMaxY(self.TEXTLabel.frame) +margin;
        CGFloat pictureW = 100;
        CGFloat pictureH = pictureW;
        self.pictureImageView.frame = CGRectMake(pictureX, pictureY, pictureW, pictureH);
    }

}

- (void)setStatus:(ZJStatus *)status{
    _status = status;
    self.iconImageView.image = [UIImage imageNamed:status.icon];
    self.nameLabel.text = status.name;
    self.TEXTLabel.text = status.text;
    // 图片
    if (status.picture) {
        self.pictureImageView.hidden = NO;
        self.pictureImageView.image = [UIImage imageNamed:status.picture];
    }
    else {
        self.pictureImageView.hidden = YES;

    }
    // vip 图标
    if (status.vip) {
        self.vipImageView.hidden = NO;

        self.nameLabel.textColor = [UIColor orangeColor];
    }else{
        self.vipImageView.hidden = YES;
        self.nameLabel.textColor = [UIColor blackColor];
    }

}

在控制器中:

#import "ZJStatus.h"
#import "ZJStatusCell.h"
// 导入第三方数据转模型框架MJExtension
#import "MJExtension.h"

@interface ViewController ()

/** status的数组 */
@property (nonatomic,strong) NSArray *statuses;
@end

@implementation ViewController

- (NSArray *)statuses{
    if (!_statuses) {
        _statuses = [ZJStatus objectArrayWithFilename:@"statuses.plist"];
    }
    return _statuses;

}

 NSString *ID = @"status";
- (void)viewDidLoad {
    [super viewDidLoad];
// 注册
    [self.tableView registerClass:[ZJStatusCell class] forCellReuseIdentifier:ID];

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

}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    ZJStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    cell.status = self.statuses[indexPath.row];
    return cell
    ;
}

#pragma mark - 通过代理方法来算高度

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 从模型中取出数据
    ZJStatus *status = self.statuses[indexPath.row];
    CGFloat margin = 10;
    CGFloat cellHeight = 0;

    // 1.设置头像的位置
    CGFloat iconX = margin;
    CGFloat iconY = margin;
    CGFloat iconW = 40;
    CGFloat iconH = iconW;
   CGRect iconImageView = CGRectMake(iconX, iconY, iconW, iconH);

    // 2.文字
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(iconImageView) + margin;
    CGFloat textW = [UIScreen mainScreen].bounds.size.width - iconX * 2;
    CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
    NSDictionary *textSize = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0]
                               };

    CGFloat textH = [status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;

     CGRect TEXTLabel  = CGRectMake(textX, textY, textW, textH);

    // 配图
    if (status.picture) {
        CGFloat pictureX = textX;
        CGFloat pictureY = CGRectGetMaxY(TEXTLabel) +margin;
        CGFloat pictureW = 100;
        CGFloat pictureH = pictureW;
        CGRect pictureImageView  = CGRectMake(pictureX, pictureY, pictureW, pictureH);

 // 如果有图片 cellHeight的Y就等于图片的最大值
        cellHeight = CGRectGetMaxY(pictureImageView);
    }
    else {
// 如果没有图片 cellHeight的Y就等于文字边距的最大值

        cellHeight = CGRectGetMaxY(TEXTLabel);

    }
    cellHeight += margin;

    return cellHeight;
}

这种完成自定义不等高cell方式很low在实现代理方法来算高度的时候又把ZJStatusView中的设置位置方式写了一遍,这样写性能会有所下降,为了提高性能,可采用MVVM设计模式进行实现,后面会单另做MVVC设计模式的分享 。

三、根据文字来创建自适应大小方式。

  // 自适应文字及高度显示
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(iconImageView) + margin;
// 设置文字的自适应宽度 ,屏幕的宽度减去两边的间距
    CGFloat textW = [UIScreen mainScreen].bounds.size.width - iconX * 2;

// 设置文字显示的最大高度
    CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
// 字典包装文字本身大小
    NSDictionary *textSize = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0]
                               };
//  算出文字的自适应高度
    CGFloat textH = [status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;

     CGRect TEXTLabel  = CGRectMake(textX, textY, textW, textH);


// 自适应文字宽度显示
    CGFloat nameX = CGRectGetMaxX(self.iconImageView.frame) + margin;
    CGFloat nameY = iconY;
 // 计算文字本身所占据的尺寸
    NSDictionary *nameAttri = @{NSFontAttributeName :[UIFont systemFontOfSize:14.0]
                               };
    CGSize nameSize = [self.status.name sizeWithAttributes:nameAttri];
    // 包装成结构体
    self.nameLabel.frame = (CGRect){{nameX,nameY},nameSize};
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值