记一次填坑的cell中有label自适应高度的问题

前言:

记一次填坑的cell中有label自适应高度的问题_第1张图片
jl.jpg

自适应在日常工作中的场景还是相当广泛的,而当接收旧项目,看着满目疮痍的代码像一个残喘的病人,该如何下手,治疗病症;便是doctor该思考的问题了.如果是新页面的自适应,那还好说些,可是如果业务逻辑向关联性很多,一个界面被复用过n多次,牵一发动全身的情况就要好好斟酌了.

记一次填坑的cell中有label自适应高度的问题_第2张图片
1476863059_78.jpg

话不多说,不管iOS7,8还是9,10的自适应,最根本的应该就是frame的计算上.
虽然略显麻烦,但是确保可扩展可维护性这才是正确的.

场景介绍:

在tableview的cell中,有着控件个数不固定,长宽高不固定的情况;
比如,一个界面被复用了很多次,第一次进来,要求只有一个label,
但是label上的内容长度,高度都不固定,并且cell要对其进行自适应;
一个label的自适应,搞定了,那么就不会介意有imageview,等等的自定义的view了;所以接下来就详细的说一下cell自适应label的不固定的高和宽吧.

进入高能:

一个自定义cell,一个进行Frame计算的工具Frame类,如此便可.

在对应的控制中需要有个数组,用来保存loadData中得到的模型数据.

@property (nonatomic ,strong)NSArray *contentFrame;

最好在loadData中直接返回的是模型的数组,这样做在整体架构来讲是很好的处理方式


接着跟进模型数组创建frame模型数组,也就是对得到的原始数据进行加工,让它具有一个frame模型;
- (NSArray *)contentFrame
{
NSMutableArray *models = [NSMutableArray arrayWithCapacity:_dataList.count];

         for (TCWorkMessageSamllList *lis in _dataList) {
         // 根据模型数据创建frame模型
          VDFrame *vdF = [[VDFrame alloc] init];
          vdF.model = lis;

         [models addObject:vdF];
            }
             self.contentFrame = [models copy];
 
     return _contentFrame;
 }

那来看一下VDFrame里面具体的实现吧
#import
#import "TCWorkMessageSamllList.h"

@interface VDFrame : NSObject

@property (nonatomic, strong) TCWorkMessageSamllList *model;
@property (nonatomic, assign) CGRect introF;
@property (nonatomic, assign) CGRect sLabelF;
@property (nonatomic, assign) CGRect tLabelF;
@property (nonatomic, assign) CGFloat cellHeight;
@end
  • TCWorkMessageSamllList是一个模型,VDFrame需要跟进模型中的content来计算cell实际的高度;

//  专门用来保存每一行数据的frame, 计算frame
#import "VDFrame.h"
#define VDNameFont [UIFont systemFontOfSize:15]
#define VDTextFont [UIFont systemFontOfSize:16]

@implementation VDFrame

- (void)setModel:(TCWorkMessageSamllList *)model
 {
 _model = model;

 // 间隙
 CGFloat padding = 10;

 CGFloat introLabelX = padding;
 CGFloat introLabelY = padding;
 CGSize textSize =  [self sizeWithString:_model.content font:VDTextFont maxSize:CGSizeMake(300, MAXFLOAT)];

 CGFloat introLabelW = textSize.width;
 CGFloat introLabelH = textSize.height;

 self.introF = CGRectMake(introLabelX, introLabelY, SCREEN_WIDTH - 40, introLabelH);

  CGFloat cellHeight = 0;
 if (_model.handleStatus) {
     CGSize slabelSize = [self sizeWithString:_model.handleStatus font:NJTextFont maxSize:CGSizeMake(300, MAXFLOAT)];
     CGFloat slabelW = slabelSize.width;
     CGFloat slabelH = slabelSize.height;
     self.sLabelF = CGRectMake(padding, CGRectGetMaxY(self.introF) +padding, slabelW, slabelH);
     
     CGSize tlabelSize = [self sizeWithString:_model.applyDate font:VDTextFont maxSize:CGSizeMake(300, MAXFLOAT)];
     CGFloat tlabelW = tlabelSize.width;
     CGFloat tlabelH = tlabelSize.height;
     self.tLabelF = CGRectMake(SCREEN_WIDTH-padding - tlabelW, CGRectGetMaxY(self.introF) +padding, tlabelW, tlabelH);
     
     self.cellHeight = CGRectGetMaxY(self.tLabelF) + padding;
 }else{

 self.cellHeight = CGRectGetMaxY(self.introF) + padding;
 }
 }

/**
 *  计算文本的宽高
 *
 *  @param str     需要计算的文本
 *  @param font    文本显示的字体
 *  @param maxSize 文本显示的范围
 *
 *  @return 文本占用的真实宽高
 */
 - (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
 {
     NSDictionary *dict = @{NSFontAttributeName : font};
     // 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围
     // 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围
     CGSize size =  [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
     return size;
     }
    @end

至此,根据content的具体内容来计算宽高已经完成;
那么接下来就来到自定义的cell里来搞事情吧
#import
@class VDFrame;
@interface TCWorkMesSubTableViewCell : UITableViewCell

@property (nonatomic,strong)UILabel  *mLableTitle;

@property(nonatomic, strong) UILabel *sLabel;

@property(nonatomic, strong) UILabel *tLabel;

@property (nonatomic ,strong)VDFrame *vDFrame;

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

@end

如上的cell中,定义了三个label,一个cell的类方法;

在cell的.m文件中
+ (instancetype)cellWithTableView:(UITableView *)tableView
{
static NSString *identifier = @"cell";
TCWorkMesSubTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[TCWorkMesSubTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}

    return cell;
}

也就是把cell的创建方法,不交给控制器,具体实现,交给他自己各司其职
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// 让自定义Cell和系统的cell一样, 一创建出来就拥有一些子控件提供给我们使用
UILabel *introLabel = [[UILabel alloc] init];
introLabel.font = [UIFont systemFontOfSize:13];
introLabel.numberOfLines = 0;
// introLabel.backgroundColor = [UIColor greenColor];
[self.contentView addSubview:introLabel];
self.mLableTitle = introLabel;

            UILabel *statusLabel = [[UILabel alloc] init];
            statusLabel.font = [UIFont systemFontOfSize:13];
            statusLabel.numberOfLines = 0;
            statusLabel.textColor = [UIColor redColor];
            [self.contentView addSubview:statusLabel];
            self.sLabel = statusLabel;
            
            UILabel *timeLabel = [[UILabel alloc] init];
            timeLabel.font = [UIFont systemFontOfSize:13];
            timeLabel.numberOfLines = 0;
            [self.contentView addSubview:timeLabel];
            self.tLabel = timeLabel;
            
         }
     return self;
 }

在setVDFrame里面对label们进行赋值,并且设置frame
- (void)setVDFrame:(VDFrame *)vDFrame{
_vDFrame = vDFrame;

     // 1.给子控件赋值数据
     [self settingData];
     // 2.设置frame
     [self settingFrame];
}
 - (void)settingData
 {
 TCWorkMessageSamllList *intro = _vDFrame.model;
 self.mLableTitle.text =intro.content;
 self.sLabel.text = intro.handleStatus;
 self.tLabel.text = intro.applyDate;
 
}
- (void)settingFrame
 {

 self.mLableTitle.frame = self.vDFrame.introF;
 self.sLabel.frame = self.vDFrame.sLabelF;
 self.tLabel.frame = self.vDFrame.tLabelF;
 }

没错离成功还差一小步,

现在,可以把目光转移回控制器的UItableview的代理方法里了
来到

 cellForRowAtIndexPath的方法里做一件很爽的事
cell.vDFrame = self.contentFrame[indexPath.row];

一句话搞定,

来到heightForRowAtIndexPath里
VDFrame *vdF = self.contentFrame[indexPath.row];
    return vdF.cellHeight;

至此,


记一次填坑的cell中有label自适应高度的问题_第3张图片
bang

自适应完结.,当跟进自己的需求进行添砖加瓦如上frame以及cell所做即可.

你可能感兴趣的:(记一次填坑的cell中有label自适应高度的问题)