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

前言:

jl.jpg

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

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 <Foundation/Foundation.h>
#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 <UIKit/UIKit.h>
@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;

至此,


bang

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容