1.效果图:
2.写出的详细步骤:
(1)向Main.storyboard里的控制器中添加一个UITableView控件。
(2)ViewController类遵守两个协议(UITableViewDataSource , UITableViewDelegate),并使tableView属性与UITableView控件连线,设置当前控制器成为tableView的数据源对象和代理对象,实现以下方法:
#pragma mark - 数据源方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
(3)发现没有数据,那么需要字典转模型;数据模型:QJStatuse;信息模型:QJStatuseFrame。》QJStatuse:只有五个属性值对应字典的每个Key。
》QJStatuseFrame:拥有一个QJStatuse对象(即数据)和每个数据控件的frame。提高性能。
问题:自写一个 计算文字的frame方法:
/** 返回文字真实的Size */ - (CGSize) sizeWithText:(NSString *)text Size:(CGSize)size font:(UIFont *)font{ NSDictionary * attrib = @{NSFontAttributeName : font}; return [text boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attrib context:nil].size; }(4)并发现每个Cell是不一样的,所以需要用代码自定义一个UITableViewCell -->QJStatuseCell继承UITableViewCell。那么QJSatuseCell类必须要提够一些方法,使上面数据源协议的第三个方法可以实现:
》重写- initWithStyle: reuseIdentifier: 对象方法,用于添加控件。
》创建一个QJSatuseCell方法, 并调用重写上述方法向QJSatuseCell对象.contentView中添加五个不同的控件(iconImgView,nameLable,vipImgView,text1Lable,pictureImgView),但不设置任何数据,因为该方法只用来创建Cell对象。
》写出该对象属性_statuseFrame的 setter,用于:根据传入的statuseFrame参数 初始化每个对应Cell内五个控件的:1.内容 2.设置frame
(5)最后每个Cell的高度不一要,那么只要实现代理协议中的一个方法:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ QJStatuseFrame * sta = self.statuseFrames[indexPath.row]; return sta.cellHeight; }
Model:
// // QJStatuse.h // 09-自定义cell-微博 // // Created by 瞿杰 on 15/9/30. // #import <UIKit/UIKit.h> @interface QJStatuse : NSObject @property (nonatomic,copy)NSString * icon; @property (nonatomic,copy)NSString * name; @property (nonatomic,copy)NSString * text; @property (nonatomic,copy)NSString * picture; @property (nonatomic,assign)NSNumber * vip; + (instancetype)statuseWithDictionary:(NSDictionary *)dic; - (instancetype)initWithDictionary:(NSDictionary *)dic; @end
// // QJStatuse.m // 09-自定义cell-微博 // // Created by 瞿杰 on 15/9/30. // Copyright © 2015年 itcast. All rights reserved. // #import "QJStatuse.h" @implementation QJStatuse + (instancetype)statuseWithDictionary:(NSDictionary *)dic{ return [[self alloc]initWithDictionary:dic]; } - (instancetype)initWithDictionary:(NSDictionary *)dic{ if (self = [super init]) { self.icon = dic[@"icon"]; self.name = dic[@"name"]; self.text = dic[@"text"]; self.picture = dic[@"picture"]; self.vip = dic[@"vip"]; } return self; } @end
// // QJStatusFrame.h // 09-自定义cell-微博 // // Created by 瞿杰 on 15/9/30. // Copyright © 2015年 itcast. All rights reserved. // #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @class QJStatuse; @interface QJStatuseFrame : NSObject @property (nonatomic, strong) QJStatuse *statuse; /** * 头像的frame */ @property (nonatomic, assign, readonly) CGRect iconFrame; /** * 昵称的frame */ @property (nonatomic, assign, readonly) CGRect nameFrame; /** * 会员图标的frame */ @property (nonatomic, assign, readonly) CGRect vipFrame; /** * 正文的frame */ @property (nonatomic, assign, readonly) CGRect textFrame; /** * 配图的frame */ @property (nonatomic, assign, readonly) CGRect pictureFrame; /** * cell的高度 */ @property (nonatomic, assign, readonly) CGFloat cellHeight; @end
// // QJStatuseFrame.m // 09-自定义cell-微博 // // Created by 瞿杰 on 15/9/30. // Copyright © 2015年 itcast. All rights reserved. // 每个QJStatuseFrame对象都拥有 每个控件的 信息 和 frame #import "QJStatuseFrame.h" #import "QJStatuse.h" #define nameFont [UIFont systemFontOfSize:14] #define textFont [UIFont systemFontOfSize:16] @implementation QJStatuseFrame /** 属性_statuse的setter方法 */ - (void)setStatuse:(QJStatuse *)statuse{ //每个控件的信息 _statuse = statuse ; //间隔 CGFloat padding = 10 ; //iconFrame CGFloat iconX = padding ; CGFloat iconY = padding ; CGFloat iconW = 50; CGFloat iconH = 50; _iconFrame = CGRectMake(iconX, iconY, iconW, iconH); //nameFrame CGSize nameSize = [self sizeWithText:self.statuse.name Size:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) font:nameFont]; CGFloat nameX = CGRectGetMaxX(self.iconFrame) + padding; CGFloat nameY = self.iconFrame.origin.y + (self.iconFrame.size.height - nameSize.height)*0.5; _nameFrame = CGRectMake(nameX, nameY, nameSize.width, nameSize.height); //vipFrame CGFloat vipX = CGRectGetMaxX(self.nameFrame) + padding; CGFloat vipY = self.nameFrame.origin.y ; CGFloat vipW = 14; CGFloat vipH = 14; _vipFrame = CGRectMake(vipX, vipY, vipW, vipH); //正文textFrame CGFloat textX = padding ; CGFloat textY = CGRectGetMaxY(self.iconFrame) + padding; CGSize textSize = [self sizeWithText:self.statuse.text Size:CGSizeMake(394, CGFLOAT_MAX) font:textFont]; _textFrame = CGRectMake(textX, textY, textSize.width, textSize.height); //符加图pictureFrame if (self.statuse.picture ) { CGFloat pictureX = padding ; CGFloat pictureY = CGRectGetMaxY(self.textFrame); CGFloat pictureW = 100; CGFloat pictureH = 100; _pictureFrame = CGRectMake(pictureX, pictureY, pictureW, pictureH); _cellHeight = CGRectGetMaxY(self.pictureFrame) + padding; } else{ _pictureFrame = CGRectZero ; _cellHeight = CGRectGetMaxY(self.textFrame) + padding; } } /** 返回文字真实的Size */ - (CGSize) sizeWithText:(NSString *)text Size:(CGSize)size font:(UIFont *)font{ NSDictionary * attrib = @{NSFontAttributeName : font}; return [text boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attrib context:nil].size; } @end
// // QJStatuseCell.h // 09-自定义cell-微博 // // Created by 瞿杰 on 15/9/30. // Copyright © 2015年 itcast. All rights reserved. // #import <UIKit/UIKit.h> @class QJStatuseFrame; @interface QJStatuseCell : UITableViewCell @property (nonatomic , weak)QJStatuseFrame * statuseFrame; + (instancetype)statuseCellWithTableView:(UITableView *)tableView; @end
// // QJStatuseCell.m // 09-自定义cell-微博 // // Created by 瞿杰 on 15/9/30. // Copyright © 2015年 itcast. All rights reserved. // #import "QJStatuseCell.h" #import "QJStatuseFrame.h" #import "QJStatuse.h" #define nameFont [UIFont systemFontOfSize:14] #define textFont [UIFont systemFontOfSize:16] @interface QJStatuseCell () @property (nonatomic , weak)UIImageView * iconImgView ; @property (nonatomic , weak)UILabel * nameLable ; @property (nonatomic , weak)UIImageView * vipImgView ; @property (nonatomic , weak)UILabel * text1Lable ; @property (nonatomic , weak)UIImageView * pictureImgView ; @end @implementation QJStatuseCell + (instancetype)statuseCellWithTableView:(UITableView *)tableView{ // 可重用的标识符 NSString * ID = @"statuseCell"; QJStatuseCell * cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[self alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } return cell; } /** 重写从父类继承的对象方法:只添加控件,不设置任何数据,因为数据是不确定的 */ - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { //添加头象 UIImageView * iconImgView = [[UIImageView alloc]init]; [self.contentView addSubview:iconImgView]; self.iconImgView = iconImgView; //添加nameLable UILabel * nameLable = [[UILabel alloc]init]; nameLable.font = nameFont; [self.contentView addSubview:nameLable]; self.nameLable = nameLable; //添加vipImgView UIImageView * vipImgView = [[UIImageView alloc]init]; [self.contentView addSubview:vipImgView]; self.vipImgView = vipImgView; //添加text1Lable UILabel * textLalbe = [[UILabel alloc]init]; textLalbe.font = textFont ; textLalbe.numberOfLines = 0; // 不限制行数,自动换行 [self.contentView addSubview:textLalbe]; self.text1Lable = textLalbe ; //添加pictureImgView UIImageView * pictureImgView = [[UIImageView alloc]init]; [self.contentView addSubview:pictureImgView]; self.pictureImgView = pictureImgView ; } return self ; } /** * 初始化每个对应Cell内五个控件的:1.内容 2.设置frame */ - (void)setStatuseFrame:(QJStatuseFrame *)statuseFrame{ _statuseFrame = statuseFrame; // 初始化头象 self.iconImgView.image = [UIImage imageNamed:statuseFrame.statuse.icon]; self.iconImgView.frame = statuseFrame.iconFrame; // 初始化nameLable self.nameLable.text = statuseFrame.statuse.name; self.nameLable.frame = statuseFrame.nameFrame; // 初始化vipImgView if ([statuseFrame.statuse.vip intValue]) { self.nameLable.textColor = [UIColor redColor]; self.vipImgView.hidden = NO; self.vipImgView.image = [UIImage imageNamed:@"vip"]; self.vipImgView.frame = statuseFrame.vipFrame; } else{ self.nameLable.textColor = [UIColor blackColor]; self.vipImgView.hidden = YES ; } // 初始化textLable self.text1Lable.text = statuseFrame.statuse.text; self.text1Lable.frame = statuseFrame.textFrame; // 初始化pictureImgView, // 无需判断是否需要隐藏,因为如果没有图,那么pictureFrame = CGRectZero self.pictureImgView.image = [UIImage imageNamed:statuseFrame.statuse.picture]; self.pictureImgView.frame = statuseFrame.pictureFrame; } //- (void)awakeFromNib { // // Initialization code //} // //- (void)setSelected:(BOOL)selected animated:(BOOL)animated { // [super setSelected:selected animated:animated]; // // // Configure the view for the selected state //} @end
// // ViewController.h // 09-自定义cell-微博 // // Created by 瞿杰 on 15/9/30. // Copyright © 2015年 itcast. All rights reserved. // #import <UIKit/UIKit.h> @interface ViewController : UIViewController @end
// // ViewController.m // 09-自定义cell-微博 // // Created by 瞿杰 on 15/9/30. // Copyright © 2015年 itcast. All rights reserved. // #import "ViewController.h" #import "QJStatuse.h" #import "QJStatuseFrame.h" #import "QJStatuseCell.h" @interface ViewController ()<UITableViewDataSource , UITableViewDelegate> @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (strong,nonatomic)NSArray * statuseFrames; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 设置数据源 self.tableView.dataSource = self; self.tableView.delegate = self ; } - (BOOL)prefersStatusBarHidden{ return YES; } - (NSArray *)statuseFrames{ if (_statuseFrames == nil) { NSString * path = [[NSBundle mainBundle]pathForResource:@"statuses.plist" ofType:nil]; NSArray * statuArray = [NSArray arrayWithContentsOfFile:path]; NSMutableArray * statuseFrames = [NSMutableArray array]; for(NSDictionary * dic in statuArray){ QJStatuse * stat = [QJStatuse statuseWithDictionary:dic]; QJStatuseFrame * statFrame = [[QJStatuseFrame alloc]init]; statFrame.statuse = stat ; [statuseFrames addObject:statFrame]; } _statuseFrames = statuseFrames; } return _statuseFrames; } #pragma mark - 数据源方法 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.statuseFrames.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ // 创建一个cell QJStatuseCell * cell = [QJStatuseCell statuseCellWithTableView:tableView]; //初始化内容 cell.statuseFrame = self.statuseFrames[indexPath.row]; return cell; } #pragma mark - 代理方法 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ QJStatuseFrame * sta = self.statuseFrames[indexPath.row]; return sta.cellHeight; } @end