第一步:创建微博模型,完成字典转模型
#import <Foundation/Foundation.h> //#import <UIKit/UIKit.h> /** * 第一步:创建微博模型,完成字典转模型 */ @interface LLWeiBo : NSObject /** * icon */ @property (nonatomic, copy) NSString *icon; /** * name */ @property (nonatomic, copy) NSString *name; /** * vip */ @property (nonatomic, assign, getter=isVip) BOOL vip; /** * text */ @property (nonatomic, copy) NSString *text; /** * picture */ @property (nonatomic, copy) NSString *picture; - (instancetype)initWithDic:(NSDictionary *)dic; + (instancetype)weiBoWithDic:(NSDictionary *)dic; @end
#import "LLWeiBo.h" @implementation LLWeiBo - (instancetype)initWithDic:(NSDictionary *)dic { if (self = [super init]) { [self setValuesForKeysWithDictionary:dic]; } return self; } + (instancetype)weiBoWithDic:(NSDictionary *)dic { return [[self alloc] initWithDic:dic]; } @end
第二步:确定cell的高度
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #define NAMEFONT [UIFont systemFontOfSize:14] #define TEXTFONT [UIFont systemFontOfSize:15] @class LLWeiBo; @interface LLWeiBoFrame : NSObject @property (nonatomic, strong) LLWeiBo *weiBo; @property (nonatomic, assign, readonly) CGRect iconF; @property (nonatomic, assign, readonly) CGRect nameF; @property (nonatomic, assign, readonly) CGRect vipF; @property (nonatomic, assign, readonly) CGRect textF; @property (nonatomic, assign, readonly) CGRect picF; @property (nonatomic, assign, readonly) CGFloat cellHeight; @end
#import "LLWeiBoFrame.h" #import "LLWeiBo.h" @implementation LLWeiBoFrame - (void)setWeiBo:(LLWeiBo *)weiBo { _weiBo = weiBo; CGFloat margin = 10.0; // 头像 CGFloat iconX = margin; CGFloat iconY = margin; CGFloat iconHW = 30; _iconF = CGRectMake(iconX, iconY, iconHW, iconHW); /** * 设置到计算文字的size 与三个变量有关1,文字,2,字体,3,文字要显示最大size的限制 */ // 名称 CGFloat nameX = CGRectGetMaxX(_iconF) + margin; CGSize nameSize = [self sizeOfText:self.weiBo.name Font:NAMEFONT MaxSize:CGSizeMake(MAXFLOAT, MAXFLOAT)]; CGFloat nameY = (iconHW - nameSize.height) * 0.5 + iconY; _nameF = CGRectMake(nameX, nameY, nameSize.width, nameSize.height); // 会员 CGFloat vipX = CGRectGetMaxX(_nameF) + margin; CGFloat vipY = nameY; CGFloat vipWH = 15; _vipF = CGRectMake(vipX, vipY, vipWH, vipWH); // 正文 CGFloat textX = margin; CGFloat textY = CGRectGetMaxY(_iconF) + margin; CGSize textSize = [self sizeOfText:self.weiBo.text Font:TEXTFONT MaxSize:CGSizeMake(300, MAXFLOAT)]; _textF = CGRectMake(textX, textY, textSize.width, textSize.height); // 图片 CGFloat picX = margin; CGFloat picY = CGRectGetMaxY(_textF) + margin; CGFloat picWH = 100; _picF = CGRectMake(picX, picY, picWH, picWH); if (self.weiBo.picture) { _cellHeight = CGRectGetMaxY(_picF) + margin; } else { _cellHeight = CGRectGetMaxY(_textF) + margin; } } #pragma mark - 计算文字size - (CGSize)sizeOfText:(NSString *)text Font:(UIFont *)font MaxSize:(CGSize)maxSize { NSDictionary *attrs = @{NSFontAttributeName : font }; return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size; } @end
第3步:创建cell展示数据
#import <UIKit/UIKit.h> @class LLWeiBoFrame; @interface LLWeiBoCell : UITableViewCell @property (nonatomic, strong) LLWeiBoFrame *weiBoFrame; + (instancetype)weiBoCell:(UITableView *)tableView; @end
#import "LLWeiBoCell.h" #import "LLWeiBoFrame.h" #import "LLWeiBo.h" @interface LLWeiBoCell () @property (nonatomic, weak) UIImageView *iconView; @property (nonatomic, weak) UILabel *nameView; @property (nonatomic, weak) UIImageView *vipView; @property (nonatomic, weak) UILabel *textView; @property (nonatomic, weak) UIImageView *picView; @end @implementation LLWeiBoCell + (instancetype)weiBoCell:(UITableView *)tableView { static NSString *ID = @"weiBoCell"; LLWeiBoCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (!cell) { /** cell如果不存在,我们自定义创建cell,或者通过storyboard创建,或者加载xib,这个我们自定义创建cell */ cell = [[LLWeiBoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } return cell; } - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { /** * 初始化cell创建cell的子控件 */ // 头像 UIImageView *iconView = [[UIImageView alloc] init]; [self.contentView addSubview:iconView]; self.iconView = iconView; // 名称 UILabel *nameView = [[UILabel alloc] init]; [self.contentView addSubview:nameView]; nameView.textColor = [UIColor blackColor]; nameView.font = NAMEFONT; self.nameView = nameView; // 会员 UIImageView *vipView = [[UIImageView alloc] init]; [self.contentView addSubview:vipView]; vipView.image = [UIImage imageNamed:@"vip"]; self.vipView = vipView; // 正文 UILabel *textView = [[UILabel alloc] init]; [self.contentView addSubview:textView]; textView.numberOfLines = 0; textView.font = TEXTFONT; self.textView = textView; // 图片 UIImageView *picView = [[UIImageView alloc] init]; [self.contentView addSubview:picView]; self.picView = picView; } return self; } - (void)setWeiBoFrame:(LLWeiBoFrame *)weiBoFrame { _weiBoFrame = weiBoFrame; // 1,设置cell子控件数据 [self setSubviewsDate]; // 2,设置cell子控件的frame [self setSubviewFrame]; } - (void)setSubviewsDate { LLWeiBo *weiBo = self.weiBoFrame.weiBo; self.iconView.image = [UIImage imageNamed:weiBo.icon]; self.nameView.text = weiBo.name; /** * 因为cell的重用问题,这里赋值数据要全部重新赋值,否则容易出错 */ if (weiBo.isVip) { self.vipView.hidden = NO; self.nameView.textColor = [UIColor redColor]; } else { self.vipView.hidden = YES; self.nameView.textColor = [UIColor blackColor]; } self.textView.text = weiBo.text; if (weiBo.picture) { self.picView.image = [UIImage imageNamed:weiBo.picture]; self.picView.hidden = NO; } else{ self.picView.hidden = YES; } } - (void)setSubviewFrame { self.iconView.frame = self.weiBoFrame.iconF; self.nameView.frame = self.weiBoFrame.nameF; self.vipView.frame = self.weiBoFrame.vipF; self.textView.frame = self.weiBoFrame.textF; self.picView.frame = self.weiBoFrame.picF; } @end
第4步展示cell
#import "LLViewController.h" #import "LLWeiBo.h" #import "LLWeiBoCell.h" #import "LLWeiBoFrame.h" @interface LLViewController () @property (nonatomic, strong) NSArray *weiBoFrames; @end @implementation LLViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView.rowHeight = 200; } #pragma mark - 懒加载数据模型 - (NSArray *)weiBoFrames { if (!_weiBoFrames) { NSString *path = [[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil]; NSArray *dicArray = [NSArray arrayWithContentsOfFile:path]; NSMutableArray *tmpArray = [[NSMutableArray alloc] initWithCapacity:dicArray.count]; for (NSDictionary *dic in dicArray) { LLWeiBoFrame *weiBoFrame = [[LLWeiBoFrame alloc] init]; LLWeiBo *weibo = [LLWeiBo weiBoWithDic:dic]; weiBoFrame.weiBo = weibo; [tmpArray addObject:weiBoFrame]; } _weiBoFrames = tmpArray; } return _weiBoFrames; } #pragma mark - tableView的数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.weiBoFrames.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 1,创建cell LLWeiBoCell *cell = [LLWeiBoCell weiBoCell:tableView]; // 2,给cell设置数据 cell.weiBoFrame = self.weiBoFrames[indexPath.row]; return cell; } #pragma mark - 代理的方法 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return [self.weiBoFrames[indexPath.row] cellHeight]; } @end
补充:
使用纯代码自定义一个tableview的步骤
1.新建一个继承自UITableViewCell的类
2.重写initWithStyle:reuseIdentifier:方法
添加所有需要显示的子控件(不需要设置子控件的数据和frame, 子控件要添加到contentView中)
进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)
3.提供2个模型
数据模型: 存放文字数据\图片数据
frame模型: 存放数据模型\所有子控件的frame\cell的高度
4.cell拥有一个frame模型(不要直接拥有数据模型)
5.重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame
6.frame模型数据的初始化已经采取懒加载的方式(每一个cell对应的frame模型数据只加载一次)
代码:
/**
* 计算文本的宽高
*
* @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;
}