iOS开发项目篇—41cell的frame设计
一、简单说明
1.分层设计
在进行设计的时候,建议先分析整个cell的结构,确定了cell由哪些模块构成之后,再进一步确定每个模块中包含的子控件。
在这个微博的cell中,把这个cell分成两个大的模块。分解结构如下:
1.微博完整内容模块View
(1)原创微博view
1)头像imageView
2)自己的昵称label
3)发布的时间label
4)微博来源label
5)微博的正文
(2)转发微博
1)原作者的昵称label
2)转发的微博正文label
2.toolbar工具条模块View
(1)转发button
(2)评论button
(3)赞button
示意图:
分层设计的好处:屏蔽了最上层和最下层的处理细节,下层代码修改后,顶层不需要跟着进行修改。
(1)每个类的冗余度低,易于维护
(2)业务逻辑精准,每个类只封装自己该做的事情
2.frame的设计
对应于模块的设计,得出frame设计的示意图:
说明:需要新建5个类。管理对应的frame。
二、代码设计
1.文件结构
2.代码实现
YYStatusCell.h文件
1 // 2 // YYStatusCell.h 3 // 4 5 #import <UIKit/UIKit.h> 6 @class YYStatusFrame; 7 @interface YYStatusCell : UITableViewCell 8 #warning 注意这里不能直接使用frame作为属性名。继承自UIview,而它本身就有一个frame。 9 @property(nonatomic,strong)YYStatusFrame *statusFrame; 10 @end
YYStatusCell.m文件
1 // 2 // YYStatusCell.m 3 // 自定义cell 4 5 #import "YYStatusCell.h" 6 #import "YYStatusDetailView.h" 7 #import "YYStatusToolbar.h" 8 //#import "YYStatusDetailFrame.h" 9 #import "YYStatusFrame.h" 10 11 @interface YYStatusCell () 12 @property(nonatomic,weak)YYStatusDetailView *detailView; 13 @property(nonatomic,weak)YYStatusToolbar *toolbar; 14 @end 15 16 @implementation YYStatusCell 17 18 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 19 { 20 self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 21 if (self) { 22 //初始化子控件 23 24 //1.添加微博具体内容 25 [self setupDetailView]; 26 27 //2.添加工具条 28 [self setupToolbar]; 29 } 30 return self; 31 } 32 33 /**添加微博具体内容*/ 34 -(void)setupDetailView 35 { 36 YYStatusDetailView *detailView=[[YYStatusDetailView alloc]init]; 37 [self.contentView addSubview:detailView]; 38 self.detailView=detailView; 39 } 40 41 /**添加工具条*/ 42 -(void)setupToolbar 43 { 44 YYStatusToolbar *toolbar=[[YYStatusToolbar alloc]init]; 45 [self.contentView addSubview:toolbar]; 46 self.toolbar=toolbar; 47 } 48 49 -(void)setStatusFrame:(YYStatusFrame *)statusFrame 50 { 51 _statusFrame=statusFrame; 52 //1.微博具体内容的frame数据 53 self.detailView.detailFrame=statusFrame.StatusDetailFrame; 54 55 //2.底部工具条的frame数据 56 self.toolbar.frame=statusFrame.toolbarFrame; 57 } 58 @end
YYStatusFrame.h文件
1 // 2 // YYStatusFrame.h 3 //一个Frame包括一个cell内部所有的子控件的frame和显示数据 4 5 //获取frame--->根据传入的数据值进行计算,这里需要传入微博数据模型,对子控件的frame进行分层 6 #import <Foundation/Foundation.h> 7 @class YYStatusModel,YYStatusDetailFrame; 8 @interface YYStatusFrame : NSObject 9 10 /** 11 * toolbar工具条的frame 12 */ 13 @property(nonatomic,assign)CGRect toolbarFrame; 14 /** 15 * 微博整体内容的frame 16 */ 17 @property(nonatomic,strong)YYStatusDetailFrame *StatusDetailFrame; 18 /** 19 * cell的高度 20 */ 21 @property(nonatomic,assign)CGFloat cellHight; 22 23 //传入微博数据模型 24 @property(nonatomic,strong)YYStatusModel *status; 25 @end
YYStatusFrame.m文件
1 // 2 // YYStatusFrame.m 3 // 4 5 #import "YYStatusFrame.h" 6 #import "YYStatusDetailFrame.h" 7 8 @implementation YYStatusFrame 9 -(void)setStatus:(YYStatusModel *)status 10 { 11 _status=status; 12 //1.计算微博的具体内容(微博整体) 13 [self setupStatusDetailFrame]; 14 15 //2.计算底部工具条 16 [self setupToolbarFrame]; 17 18 //3.计算cell的高度 19 self.cellHight=CGRectGetMaxY(self.toolbarFrame); 20 } 21 22 /** 23 * 计算微博的具体内容(微博整体) 24 */ 25 -(void)setupStatusDetailFrame 26 { 27 YYStatusDetailFrame *detailFrame=[[YYStatusDetailFrame alloc]init]; 28 detailFrame.status=self.status; 29 self.StatusDetailFrame=detailFrame; 30 } 31 32 /** 33 * 计算底部工具条 34 */ 35 -(void)setupToolbarFrame 36 { 37 CGFloat toolbarX=0; 38 CGFloat toolbarW=YYScreenW; 39 CGFloat toolbarH=35; 40 CGFloat toolbarY=CGRectGetMaxY(self.StatusDetailFrame.frame); 41 self.toolbarFrame=CGRectMake(toolbarX, toolbarY, toolbarW, toolbarH); 42 } 43 @end
YYStatusDetailView.h文件
1 // 2 // YYStatusDetailView.h 3 // 4 5 #import <UIKit/UIKit.h> 6 7 @class YYStatusDetailFrame; 8 @interface YYStatusDetailView : UIView 9 @property(nonatomic,strong)YYStatusDetailFrame *detailFrame; 10 @end
YYStatusDetailView.m文件
1 // 2 // YYStatusDetailView.m 3 // 4 5 #import "YYStatusDetailView.h" 6 #import "YYStatusOriginalView.h" 7 #import "YYStatusRetweetedView.h" 8 #import "YYStatusDetailFrame.h" 9 10 @interface YYStatusDetailView () 11 @property(nonatomic,weak)YYStatusOriginalView *OriginalView; 12 @property(nonatomic,weak)YYStatusRetweetedView *retweetedView; 13 @end 14 @implementation YYStatusDetailView 15 16 - (id)initWithFrame:(CGRect)frame 17 { 18 self = [super initWithFrame:frame]; 19 if (self) { 20 //初始化子控件 21 22 //1.添加原创微博 23 [self setupOriginalView]; 24 25 //2.添加转发微博 26 [self setupRetweetedView]; 27 } 28 return self; 29 } 30 /**添加原创微博*/ 31 -(void)setupOriginalView 32 { 33 YYStatusOriginalView *OriginalView = [[YYStatusOriginalView alloc]init]; 34 [self addSubview:OriginalView]; 35 self.OriginalView=OriginalView; 36 37 } 38 /**添加转发微博*/ 39 -(void)setupRetweetedView 40 { 41 YYStatusRetweetedView *retweetedView = [[YYStatusRetweetedView alloc]init]; 42 [self addSubview:retweetedView]; 43 self.retweetedView=retweetedView; 44 } 45 46 -(void)setDetailFrame:(YYStatusDetailFrame *)detailFrame 47 { 48 _detailFrame=detailFrame; 49 50 //0.设置自己的frame 51 self.frame=detailFrame.frame; 52 53 //1.原创微博的frame的设置 54 self.OriginalView.originalFrame=detailFrame.originalFrame; 55 56 //2.转发微博的frame的设置 57 self.retweetedView.retweetedFrame=detailFrame.retweetedFrame; 58 } 59 @end
YYStatusDetailFrame.h文件
1 // 2 // YYStatusDetailFrame.h 3 // 4 5 #import <Foundation/Foundation.h> 6 7 @class YYStatusModel,YYStatusOriginalFrame,YYStatusRetweetedFrame; 8 @interface YYStatusDetailFrame : NSObject 9 10 /** 11 * 微博数据模型 12 */ 13 @property(nonatomic,strong)YYStatusModel *status; 14 15 @property(nonatomic,strong)YYStatusOriginalFrame *originalFrame; 16 @property(nonatomic,strong)YYStatusRetweetedFrame *retweetedFrame; 17 /** 18 * 自己的frame 19 */ 20 @property(nonatomic,assign)CGRect frame; 21 @end
YYStatusDetailFrame.m文件
1 // 2 // YYStatusDetailFrame.m 3 // 4 5 #import "YYStatusDetailFrame.h" 6 #import "YYStatusOriginalFrame.h" 7 #import "YYStatusRetweetedFrame.h" 8 #import "YYStatusModel.h" 9 10 @interface YYStatusDetailFrame () 11 @property(nonatomic,assign)CGFloat tempHeight; 12 @end 13 @implementation YYStatusDetailFrame 14 15 -(void)setStatus:(YYStatusModel *)status 16 { 17 _status=status; 18 //1.计算原创微博的frame 19 [self setupStatusOriginalFrame]; 20 21 //2.计算转发微博的frame 22 [self setupStatusRetweetedFrameWithStatus:status]; 23 24 //3.计算自己的frame 25 [self setupDetailFrame]; 26 27 } 28 29 /** 30 * 计算原创微博的frame 31 */ 32 -(void)setupStatusOriginalFrame 33 { 34 YYStatusOriginalFrame *originalFrame=[[YYStatusOriginalFrame alloc]init]; 35 originalFrame.status=self.status; 36 self.originalFrame=originalFrame; 37 } 38 39 /** 40 * 计算转发微博的frame 41 */ 42 -(void)setupStatusRetweetedFrameWithStatus:(YYStatusModel *)status 43 { 44 if (status.retweeted_status) { 45 YYStatusRetweetedFrame *retweetedFrame=[[YYStatusRetweetedFrame alloc]init]; 46 retweetedFrame.retweeted_status=status.retweeted_status; 47 self.retweetedFrame=retweetedFrame; 48 49 CGRect f=retweetedFrame.frame; 50 f.origin.y=CGRectGetMaxY(self.originalFrame.frame); 51 retweetedFrame.frame=f; 52 self.tempHeight=CGRectGetMaxY(self.retweetedFrame.frame); 53 }else 54 { 55 self.tempHeight=CGRectGetMaxX(self.originalFrame.frame); 56 } 57 58 } 59 60 /** 61 * 计算自己的frame 62 */ 63 -(void)setupDetailFrame 64 { 65 CGFloat x=0; 66 CGFloat y=0; 67 CGFloat w=YYScreenW; 68 CGFloat h=self.tempHeight; 69 self.frame=CGRectMake(x, y, w, h); 70 } 71 @end
YYStatusOriginal.h文件
1 // 2 // YYStatusOriginal.h 3 // 4 5 #import <UIKit/UIKit.h> 6 7 @class YYStatusOriginalFrame; 8 @interface YYStatusOriginalView : UIView 9 @property(nonatomic,strong)YYStatusOriginalFrame *originalFrame; 10 @end
YYStatusOriginal.m文件
1 // 2 // YYStatusOriginal.m 3 // 34-微博搭建cell的基本结构 4 // 5 // Created by apple on 14-7-17. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYStatusOriginalView.h" 10 #import "YYStatusOriginalFrame.h" 11 #import "YYUserModel.h" 12 #include "YYStatusModel.h" 13 #import "UIImageView+WebCache.h" 14 15 @interface YYStatusOriginalView () 16 /** 17 * 头像 18 */ 19 @property(nonatomic,weak)UIImageView *iconView; 20 /** 21 * 昵称 22 */ 23 @property(nonatomic,weak)UILabel *nameLabel; 24 /** 25 * 微博的正文 26 */ 27 @property(nonatomic,weak)UILabel *textLabel; 28 /** 29 * 时间 30 */ 31 @property(nonatomic,weak)UILabel *timeLabel; 32 /** 33 * 来源 34 */ 35 @property(nonatomic,weak)UILabel *sourceLabel; 36 37 @end 38 @implementation YYStatusOriginalView 39 40 - (id)initWithFrame:(CGRect)frame 41 { 42 self = [super initWithFrame:frame]; 43 if (self) { 44 //初始化子控件 45 //1.头像 46 UIImageView *iconView=[[UIImageView alloc]init]; 47 [self addSubview:iconView]; 48 self.iconView=iconView; 49 50 //2.昵称 51 UILabel *nameLabel=[[UILabel alloc]init]; 52 [self addSubview:nameLabel]; 53 self.nameLabel=nameLabel; 54 55 //3.正文 56 UILabel *textLabel=[[UILabel alloc]init]; 57 [self addSubview:textLabel]; 58 self.textLabel=textLabel; 59 60 //4.时间 61 UILabel *timeLabel=[[UILabel alloc]init]; 62 [self addSubview:timeLabel]; 63 self.timeLabel=timeLabel; 64 65 //5.来源 66 UILabel *sourceLabel=[[UILabel alloc]init]; 67 [self addSubview:sourceLabel]; 68 self.sourceLabel=sourceLabel; 69 70 } 71 return self; 72 } 73 74 -(void)setOriginalFrame:(YYStatusOriginalFrame *)originalFrame 75 { 76 _originalFrame=originalFrame; 77 78 //设置自己的frame 79 self.frame=originalFrame.frame; 80 81 //取出模型数据 82 YYStatusModel *status=originalFrame.status; 83 84 //设置头像的frame 85 [self.iconView setImageWithURL:[NSURL URLWithString:status.user.profile_image_url] placeholderImage:[UIImage imageWithName:@"avatar_default_small"]]; 86 self.iconView.frame=originalFrame.iconFrame; 87 88 //设置昵称的frame 89 self.nameLabel.text=status.user.name; 90 self.nameLabel.frame=originalFrame.nameFrame; 91 92 //设置正文的frame 93 self.textLabel.text=status.text; 94 self.textLabel.frame=originalFrame.textFrame; 95 96 //设置时间的frame 97 self.timeLabel.text=status.created_at; 98 self.timeLabel.frame=originalFrame.timeFrame; 99 100 //设置来源的frame 101 self.sourceLabel.text=status.source; 102 self.sourceLabel.frame=originalFrame.sourceFrame; 103 104 } 105 @end
YYStatusOriginalFrame.h文件
1 // 2 // YYStatusOriginalFrame.h 3 // 4 5 #import <Foundation/Foundation.h> 6 7 @class YYStatusModel; 8 @interface YYStatusOriginalFrame : NSObject 9 /** 10 * 微博数据模型 11 */ 12 @property(nonatomic,strong)YYStatusModel *status; 13 14 /** 昵称 */ 15 @property (nonatomic, assign) CGRect nameFrame; 16 /** 正文 */ 17 @property (nonatomic, assign) CGRect textFrame; 18 /** 来源 */ 19 @property (nonatomic, assign) CGRect sourceFrame; 20 /** 时间 */ 21 @property (nonatomic, assign) CGRect timeFrame; 22 /** 头像 */ 23 @property (nonatomic, assign) CGRect iconFrame; 24 25 /** 自己的frame */ 26 @property (nonatomic, assign) CGRect frame; 27 @end
YYStatusOriginalFrame.m文件
1 // 2 // YYStatusOriginalFrame.m 3 // 4 5 #import "YYStatusOriginalFrame.h" 6 #import "YYStatusModel.h" 7 #import "YYUserModel.h" 8 9 10 @implementation YYStatusOriginalFrame 11 -(void)setStatus:(YYStatusModel *)status 12 { 13 _status=status; 14 //1.计算头像的frame 15 CGFloat iconX=YYCellStatusInset; 16 CGFloat iconY=YYCellStatusInset; 17 CGFloat iconW=35; 18 CGFloat iconH=35; 19 self.iconFrame=CGRectMake(iconX, iconY, iconW, iconH); 20 21 //2.计算昵称的frame 22 CGFloat nameX=CGRectGetMaxX(self.iconFrame) + YYCellStatusInset; 23 CGFloat nameY=iconY; 24 CGSize nameSize=[status.user.name sizeWithFont:YYStatusOrginalNameFont]; 25 // self.iconFrame=CGRectMake(nameX, nameY, nameSize.width,nameSize.height); 26 self.nameFrame=(CGRect){{nameX,nameY},nameSize}; 27 28 //3.计算时间的frame 29 CGFloat timeX=nameX; 30 CGFloat timeY=CGRectGetMaxY(self.nameFrame)+YYCellStatusInset; 31 CGSize timeSize=[status.created_at sizeWithFont:YYStatusOrginalTimeFont]; 32 self.timeFrame=(CGRect){{timeX,timeY},timeSize}; 33 34 //4.计算发布来源的frame 35 CGFloat sourcceX=CGRectGetMaxX(self.textFrame)+YYCellStatusInset; 36 CGFloat sourcceY=timeY; 37 CGSize sourcceSize=[status.source sizeWithFont:YYStatusOrginalSourceFont]; 38 self.sourceFrame=(CGRect){{sourcceX,sourcceY},sourcceSize}; 39 40 //5.计算微博正文的frame 41 #warning 注意计算的区别 42 CGFloat textX=iconX; 43 CGFloat textY=CGRectGetMaxY(self.iconFrame)+YYCellStatusInset; 44 CGFloat maxW=YYScreenW-2*YYCellStatusInset; 45 CGSize maxSize=CGSizeMake(maxW, MAXFLOAT); 46 CGSize textSize=[status.text sizeWithFont:YYStatusOrginalTextFont constrainedToSize:maxSize]; 47 self.textFrame=(CGRect){{textX,textY},sourcceSize}; 48 49 //6.计算自己的frame 50 CGFloat x=0; 51 CGFloat y=0; 52 CGFloat w=YYScreenW; 53 CGFloat h=CGRectGetMaxY(self.textFrame)+YYCellStatusInset; 54 self.frame=CGRectMake(x, y, w, y); 55 } 56 @end
YYStatusRetweetedView.h文件
1 // 2 // YYStatusRetweetedView.h 3 // 4 5 #import <UIKit/UIKit.h> 6 @class YYStatusRetweetedFrame; 7 @interface YYStatusRetweetedView : UIView 8 @property(nonatomic,strong)YYStatusRetweetedFrame *retweetedFrame; 9 @end
YYStatusRetweetedView.m文件
1 // 2 // YYStatusRetweetedView.m 3 // 4 5 #import "YYStatusRetweetedView.h" 6 #import "YYStatusRetweetedFrame.h" 7 #import "YYStatusModel.h" 8 #import "YYUserModel.h" 9 10 @interface YYStatusRetweetedView () 11 /** 12 * 昵称 13 */ 14 @property(nonatomic,weak)UILabel *nameLabel; 15 /** 16 * 微博的正文 17 */ 18 @property(nonatomic,weak)UILabel *textLabel; 19 @end 20 @implementation YYStatusRetweetedView 21 22 - (id)initWithFrame:(CGRect)frame 23 { 24 self = [super initWithFrame:frame]; 25 if (self) { 26 //初始化子控件 27 //1.添加昵称 28 UILabel *nameLabel=[[UILabel alloc]init]; 29 [self addSubview:nameLabel]; 30 self.nameLabel=nameLabel; 31 32 //2.添加微博正文 33 UILabel *textLabel=[[UILabel alloc]init]; 34 [self addSubview:textLabel]; 35 self.textLabel=textLabel; 36 } 37 return self; 38 } 39 40 -(void)setRetweetedFrame:(YYStatusRetweetedFrame *)retweetedFrame 41 { 42 _retweetedFrame=retweetedFrame; 43 44 //取出对应的数据模型 45 YYStatusModel *retweeted_status=retweetedFrame.retweeted_status; 46 47 //设置自己的frame 48 self.frame=retweetedFrame.frame; 49 50 //设置昵称的frame 51 self.nameLabel.text=retweeted_status.user.name; 52 self.nameLabel.frame=retweetedFrame.nameFrame; 53 54 //设置正文的frame 55 self.textLabel.text=retweeted_status.text; 56 self.textLabel.frame=retweetedFrame.textFrame; 57 } 58 59 @end
YYStatusRetweetedFrame.h文件
1 // 2 // YYStatusRetweetedFrame.h 3 // 4 5 #import <Foundation/Foundation.h> 6 7 @class YYStatusModel; 8 @interface YYStatusRetweetedFrame : NSObject 9 /** 10 * 转发微博数据模型 11 */ 12 @property(nonatomic,strong)YYStatusModel *retweeted_status; 13 14 /** 昵称 */ 15 @property (nonatomic, assign) CGRect nameFrame; 16 /** 正文 */ 17 @property (nonatomic, assign) CGRect textFrame; 18 19 /** 自己的frame */ 20 @property (nonatomic, assign) CGRect frame; 21 @end
YYStatusRetweetedFrame.m文件
1 // 2 // YYStatusRetweetedFrame.m 3 // 4 5 #import "YYStatusRetweetedFrame.h" 6 #import "YYStatusModel.h" 7 #import "YYUserModel.h" 8 9 @implementation YYStatusRetweetedFrame 10 -(void)setRetweeted_status:(YYStatusModel *)retweeted_status 11 { 12 _retweeted_status=retweeted_status; 13 14 //1.计算昵称的frame 15 CGFloat nameX=YYCellStatusInset; 16 CGFloat nameY=YYCellStatusInset; 17 CGSize nameSize=[retweeted_status.user.name sizeWithFont:YYStatusRetweetedNameFont]; 18 self.nameFrame=(CGRect){{nameX,nameY},nameSize}; 19 20 //2.计算转发微博的正文的frame 21 CGFloat textX=nameX; 22 CGFloat textY=CGRectGetMaxY(self.nameFrame)+YYCellStatusInset; 23 CGFloat maxW=YYScreenW-2*YYCellStatusInset; 24 CGSize maxSize=CGSizeMake(maxW, MAXFLOAT); 25 CGSize textSize=[retweeted_status.text sizeWithFont:YYStatusRetweetedTextFont constrainedToSize:maxSize]; 26 self.textFrame=(CGRect){{textX,textY},textSize}; 27 28 //3.计算自己的frame 29 CGFloat x=0; 30 #warning y值为在整个view中的设置,为原创微博的最大的Y值,但是在这里拿不到这个值,可以到外面进行设置 31 CGFloat y=0; 32 CGFloat w=YYScreenW; 33 CGFloat h=CGRectGetMaxY(self.textFrame)+YYCellStatusInset; 34 self.frame=CGRectMake(x, y, w, h); 35 } 36 @end
iOS开发项目篇—41cell的frame设计