198,自定义UITableViewCell(一)

198,自定义UITableViewCell(一)_第1张图片198,自定义UITableViewCell(一)_第2张图片

198,自定义UITableViewCell(一)_第3张图片198,自定义UITableViewCell(一)_第4张图片

Model:

JSStatuses.h:

#import


@interface JSStatuses : NSObject


@property (nonatomic,copy) NSString *name;

@property (nonatomic,copy) NSString *icon;

@property (nonatomic,copy) NSString *text;

@property (nonatomic,copy) NSString *picture;

@property (nonatomic,assign) BOOL vip;


- (instancetype)initWithDic:(NSDictionary *)dic;

+ (instancetype)jsStatusesWithDic:(NSDictionary *)dic;


@end


JSStatuses.m:

#import "JSStatuses.h"


@implementation JSStatuses


- (instancetype)initWithDic:(NSDictionary *)dic{

    self = [super init];

    if (self) {

        [self setValuesForKeysWithDictionary:dic];

    }

    return self;

}


+ (instancetype)jsStatusesWithDic:(NSDictionary *)dic{

    return [[self alloc]initWithDic:dic];

}


@end


JSStatusesFrame.h:

#import

#import

#import


@class JSStatuses;


@interface JSStatusesFrame : NSObject


@property (nonatomic,assign,readonly) CGRect nameF;

@property (nonatomic,assign,readonly) CGRect iconF;

@property (nonatomic,assign,readonly) CGRect textF;

@property (nonatomic,assign,readonly) CGRect vipF;

@property (nonatomic,assign,readonly) CGRect picF;


@property (nonatomic,assign,readonly) CGFloat cellHeight;

@property (nonatomic,strong) JSStatuses *statuses;


+ (NSMutableArray *)jSStatusesFrameList;


@end



JSStatusesFrame.m:

#import "JSStatusesFrame.h"

#import "JSStatuses.h"

#import "NSString+Tools.h"


#define kPadding 10

#define kIconW 30

#define kVipW 14

#define kPictureW 70

/** 姓名字体 */

#define kNameFont [UIFont systemFontOfSize:14]

/** 正文字体 */

#define kTextFont [UIFont systemFontOfSize:16]


//@synthesize iconF = _iconF;


/**

 一旦重写了readonly属性的getter方法,_的成员变量就不存在了

 

 如果还需要使用_成员变量,则需要使用@synthesize生成对应的成员变量

 */


@implementation JSStatusesFrame


- (void)setStatuses:(JSStatuses *)statuses{

    _statuses = statuses;

    

    //icon

    CGFloat iconX = kPadding;

    CGFloat iconY = kPadding;

    _iconF = CGRectMake(iconX, iconY, kIconW,kIconW);

    

    //name

    // 姓名大小由文字的长度来决定

    // boundingRectWithSize计算给定文本字符串所占的区域

    // 返回值是一个x,y = 0CGRect,w,h是计算好的宽高

    //

    // 如果要计算多行的准确高度,需要传入NSStringDrawingUsesLineFragmentOrigin选项

    // dict用于指定字体的相关属性的字典,UIKit框架中的第一个头文件

    // context: nil

    CGSize nameSize = CGSizeMake(MAXFLOAT, MAXFLOAT);

    NSDictionary *nameDic = @{NSFontAttributeName:kNameFont};

    CGRect nameRect = [_statuses.name textSizeWithSize:nameSize attributes:nameDic];

    nameRect.origin.x = CGRectGetMaxX(_iconF) + kPadding;

    nameRect.origin.y = self.iconF.origin.y;

    _nameF = nameRect;

    

    //vip

    CGFloat vipX = CGRectGetMaxX(_nameF) + kPadding;

    CGFloat vipY = self.iconF.origin.y;

    _vipF = CGRectMake(vipX, vipY, kVipW, kVipW);

    

    //text正文

    CGFloat textW = [UIScreen mainScreen].bounds.size.width - kPadding * 2;

    CGSize textSize = CGSizeMake(textW, MAXFLOAT);

    NSDictionary *textDic = @{NSFontAttributeName:kTextFont};

    CGRect textRect = [_statuses.text textSizeWithSize:textSize attributes:textDic];

    textRect.origin.x = kPadding;

    textRect.origin.y = CGRectGetMaxY(_iconF) + kPadding;

    _textF = textRect;

    

    //picture

    if (_statuses.picture.length) {

        CGFloat picX = kPadding;

        CGFloat picY = CGRectGetMaxY(_textF) + kPadding;

        _picF = CGRectMake(picX, picY, kPictureW, kPictureW);

        //计算行高

        _cellHeight = CGRectGetMaxY(_picF) + kPadding;

    }else{

        _cellHeight = CGRectGetMaxY(_textF) +kPadding;

    }

}


+ (NSMutableArray *)jSStatusesFrameList{

    NSArray *statuses = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"statuses" ofType:@".plist" ]];

    

    //字典转模型

    NSMutableArray *statusesM = [NSMutableArray array];

    for (int i = 0; i < statuses.count; i ++) {

        JSStatusesFrame *statusesFrame = [[JSStatusesFrame alloc] init];

        JSStatuses *status = [JSStatuses jsStatusesWithDic:statuses[i]];

        statusesFrame.statuses = status;

        [statusesM addObject:statusesFrame];

    }

    return statusesM;

}


@end


Views:

JSCell.h:

#import

@class JSStatusesFrame;


@interface JSCell : UITableViewCell


@property (nonatomic,strong) JSStatusesFrame *statusesFrame;


@end


JSCell.m:

#import "JSCell.h"

#import "JSStatusesFrame.h"

#import "JSStatuses.h"


#define kNameFont [UIFont systemFontOfSize:14];

#define kTextFont [UIFont systemFontOfSize:16];


@interface JSCell ()


@property (nonatomic,strong) UIImageView *iconView;

@property (nonatomic,strong) UILabel *nameView;

@property (nonatomic,strong) UIImageView *vipView;

@property (nonatomic,strong) UILabel *textView;

@property (nonatomic,strong) UIImageView *picView;


@end


@implementation JSCell


- (UIImageView *)iconView{

    if (_iconView == nil) {

        _iconView = [[UIImageView alloc] init];

        [self.contentView addSubview:_iconView];

    }

    return _iconView;

}


- (UILabel *)nameView{

    if (_nameView == nil) {

        _nameView = [[UILabel alloc] init];

        _nameView.font = kNameFont;

        [self.contentView addSubview:_nameView];

    }

    return _nameView;

}


- (UIImageView *)vipView{

    if (_vipView == nil) {

        _vipView = [[UIImageView alloc] init];

        [self.contentView addSubview:_vipView];

    }

    return _vipView;

}


- (UILabel *)textView{

    if (_textView == nil) {

        _textView = [[UILabel alloc] init];

        _textView.font = kTextFont;

        _textView.numberOfLines = 0;

        [self.contentView addSubview:_textView];

    }

    return _textView;

}


- (UIImageView *)picView{

    if (_picView == nil) {

        _picView = [[UIImageView alloc] init];

        [self.contentView addSubview:_picView];

    }

    return _picView;

}


//设置UIFrame

- (void)setStatusesFrame:(JSStatusesFrame *)statusesFrame{

    _statusesFrame = statusesFrame;

    

    //设置数据

    [self setStatusData];

    

    //设置Frame

    [self setFrame];

}


- (void)setStatusData{

    

    //iconView

    JSStatuses *statuses = self.statusesFrame.statuses;

    self.iconView.image = [UIImage imageNamed:statuses.icon];

    

    //nameView

    self.nameView.text = statuses.name;

    

    //vipView

    if (statuses.vip) {

        self.vipView.hidden = false;

        self.nameView.textColor = [UIColor redColor];

        self.vipView.image = [UIImage imageNamed:@"vip"];

    }else{

        self.vipView.hidden = true;

        self.nameView.textColor = [UIColor blackColor];

    }

    

    //textView

    self.textView.text = statuses.text;

    

    //picView

    if (self.statusesFrame.statuses.picture.length >0) {

        self.picView.hidden = false;

        self.picView.image = [UIImage imageNamed:statuses.picture];

    }else{

        self.picView.hidden = true;

    }

    

}


-(void)setFrame{

    

    //iconView

    self.iconView.frame = self.statusesFrame.iconF;

    

    //nameView

    self.nameView.frame = self.statusesFrame.nameF;

    

    //vipView

    self.vipView.frame = self.statusesFrame.vipF;

    

    //textView

    self.textView.frame = self.statusesFrame.textF;

    

    //picView

    if(self.statusesFrame.statuses.picture.length >0)

    self.picView.frame = self.statusesFrame.picF;

    

}


@end


Other:

NSString+Tools.h:

#import

#import

#import


// 使用分类,可以把常用的方法,不好记的方法都抽取出来,进行归纳总结

// 随着学习的深入,我们每个人都会建立一大套属于自己的分类库!

@interface NSString (Tools)


/**

 *  计算当前字符串显示所需的实际frame,返回值的x = 0, y = 0

 */


- (CGRect)textSizeWithSize:(CGSize)size attributes:(NSDictionary *)attributes;


@end


NSString+Tools.m:

#import "NSString+Tools.h"


@implementation NSString (Tools)


-(CGRect)textSizeWithSize:(CGSize)size attributes:(NSDictionary *)attributes{

    // self 就是调用当前成员方法的NSString对象

    return [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];

}


@end


Controllers:
JSViewController.m

#import "JSViewController.h"

#import "JSStatusesFrame.h"

#import "JSCell.h"


static NSString *ID = @"cell";


@interface JSViewController ()


@property (nonatomic,strong) NSMutableArray *statusesFrame;


@end



@implementation JSViewController


-(NSMutableArray *)statusesFrame{

    if (_statusesFrame == nil) {

        _statusesFrame = [JSStatusesFrame jSStatusesFrameList];

    }

    return _statusesFrame;

}


- (void)viewDidLoad {

    [super viewDidLoad];

    

    /**

     *tableView注册可重用单元格

     */

    [self.tableView registerClass:[JSCell class] forCellReuseIdentifier:ID];

}


//设置数据源

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return self.statusesFrame.count;

}


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

    /**

     Storyboard中指定了可重用标示符,同时指定了Cell的类是HMStatusCell

     

     系统会为tableView注册一个原形Cell,专门用来做可重用单元格的,一旦缓冲区中不存在

     可重用单元格,系统会使用原形Cell新实例化一个Cell用程序使用!

     

     因此如果在,Storyboard中,注册了原形Cell,就不再需要 cell == nil的判断了

     */

     //JSCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    // unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard

    // 使用这个方法,要求一定注册可重用单元格,否则就会崩溃!

    // 官方建议使用以下方法,利用程序的崩溃,及时发现问题

    JSCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath];

    JSStatusesFrame *statusFrame = self.statusesFrame[indexPath.row];

    cell.statusesFrame = statusFrame;

    return  cell;

}


#pragma mark - 代理方法

/** 计算单元格行高 */

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

    /**

     计算行高的方法,会在加载表格数据时,有多少行计算多少次 contentSize

     

     问题:此方法执行的时候,cell还没有被实例化!

     但是:行高计算是在实例化cell时,通过设置status属性,计算的=>有了status模型,就可以知道行高!

     

     问题:如何在cell实例化之前,获得行高?

     解决方法:通过status可以计算得到行高!=》再建立一个模型,专门计算所有控件的位置

     */

    JSStatusesFrame *statusesFrame = self.statusesFrame[indexPath.row];

    

    return statusesFrame.cellHeight;

}


@end



你可能感兴趣的:(IOS之UI)