关于自定义UITableViewCell的使用心得
在iOS应用中常见的界面就是列表格式,一般都使用UITableView来实现,而UITableViewCell作为UITableView的单元格同样很重要。
一般可以分成以下几步进行:
1.自定义业务模型
2.自定义UITableViewCell
2.1创建自定义cell上使用的控件,如标签、按钮、图片等
2.2根据业务数据设置控件对应的内容和展示位置
3.准备UITableView的数据源
3.1 如果列表会有多个section ,那么可以再定义一个section业务模型,同上面1步骤
3.2 section业务模型,一般有2种属性:一个是section本身属性(比如,section标题、背景色或显示图片),另一个就是该section中的业务对象的数组
3.3一个UITableView通常的数据源可以这样表示:
3.3.1 数据源整个是一个数组
3.3.1 数据源数组中的每个元素就是section业务模型对象
3.3.2 每个section业务模型对象包含2种属性:1是section自身基本信息,2是section中的业务模型数组
3.3.3 业务模型数组就是上面1中定义的,也就是我们在自定义UITableViewCell上要展示的数据。
4.将上面1、2、3整合起来实现列表界面
1.自定义业务模型
比如:BOMatch.h
// // BOMatch.h // KanGeQiuUI // // Created by zhoujianqiang on 15/9/23. // Copyright © 2015年 zhoujianqiang. All rights reserved. // #import <Foundation/Foundation.h> @interface BOMatch : NSObject @property (nonatomic,copy) NSString* team1Name;//主队名称 @property (nonatomic,copy) NSString* team1Icon;//主队头像 @property (nonatomic,assign) NSInteger team1Score;//主队比分 @property (nonatomic,copy) NSString* team2Name;//客队名称 @property (nonatomic,copy) NSString* team2Icon;//客队头像 @property (nonatomic,assign) NSInteger team2Score;//客队比分 @property (nonatomic,copy) NSString* time;//比赛时间 @property (nonatomic,assign) NSInteger attentionState;//是否关注:0=未关注,1=已关注 @property (nonatomic,assign) NSInteger videoState;//是否有视频:0=没有视频,1=有视频 @property (nonatomic,assign) NSInteger matchState;//比赛状态:0=未开始,1=进行中,2=已结束 @property (nonatomic,assign) NSInteger matchId;//比赛ID #pragma mark 对象初始化-对象方法 -(BOMatch*)initWithTeam1Name : (NSString*) tema1Name andWithTeam1Icon : (NSString*) team1Icon andWithTeam1Score : (NSInteger) team1Score andWithTeam2Name : (NSString*) team2Name andWithTeam2Icon : (NSString*) team2Icon andWithTeam2Score : (NSInteger) team2Score andWithTime : (NSString*) time andWithAttentionState : (NSInteger) attentionState andWithVideoState : (NSInteger) videoState andWithMatchState : (NSInteger) matchState andWithMatchId : (NSInteger) matchId; #pragma mark 对象初始化-类方法 +(BOMatch*)initWithTeam1Name : (NSString*) tema1Name andWithTeam1Icon : (NSString*) team1Icon andWithTeam1Score : (NSInteger) team1Score andWithTeam2Name : (NSString*) team2Name andWithTeam2Icon : (NSString*) team2Icon andWithTeam2Score : (NSInteger) team2Score andWithTime : (NSString*) time andWithAttentionState : (NSInteger) attentionState andWithVideoState : (NSInteger) videoState andWithMatchState : (NSInteger) matchState andWithMatchId : (NSInteger) matchId; @end
BOMatch.m
// // BOMatch.m // KanGeQiuUI // // Created by zhoujianqiang on 15/9/23. // Copyright © 2015年 zhoujianqiang. All rights reserved. // #import "BOMatch.h" @implementation BOMatch #pragma mark 对象初始化-对象方法 -(BOMatch*)initWithTeam1Name : (NSString*) tema1Name andWithTeam1Icon : (NSString*) team1Icon andWithTeam1Score : (NSInteger) team1Score andWithTeam2Name : (NSString*) team2Name andWithTeam2Icon : (NSString*) team2Icon andWithTeam2Score : (NSInteger) team2Score andWithTime : (NSString*) time andWithAttentionState : (NSInteger) attentionState andWithVideoState : (NSInteger) videoState andWithMatchState : (NSInteger) matchState andWithMatchId : (NSInteger) matchId { if (self=[super init]) { self.team1Name=tema1Name; self.team1Icon=team1Icon; self.team1Score=team1Score; self.team2Name=team2Name; self.team2Icon=team2Icon; self.team2Score=team2Score; self.time=time; self.attentionState=attentionState; self.videoState=videoState; self.matchState=matchState; self.matchId=matchId; } return self; }; #pragma mark 对象初始化-类方法 +(BOMatch*)initWithTeam1Name : (NSString*) tema1Name andWithTeam1Icon : (NSString*) team1Icon andWithTeam1Score : (NSInteger) team1Score andWithTeam2Name : (NSString*) team2Name andWithTeam2Icon : (NSString*) team2Icon andWithTeam2Score : (NSInteger) team2Score andWithTime : (NSString*) time andWithAttentionState : (NSInteger) attentionState andWithVideoState : (NSInteger) videoState andWithMatchState : (NSInteger) matchState andWithMatchId : (NSInteger) matchId { BOMatch* match = [[BOMatch alloc] initWithTeam1Name:tema1Name andWithTeam1Icon:team1Icon andWithTeam1Score:team1Score andWithTeam2Name:team2Name andWithTeam2Icon:team2Icon andWithTeam2Score:team2Score andWithTime:time andWithAttentionState:attentionState andWithVideoState:videoState andWithMatchState:matchState andWithMatchId:matchId]; return match; }; @end
2.自定义UITableViewCell
BOMatchTableViewCell.h
#import <UIKit/UIKit.h> #import "BOMatch.h" @protocol BOMatchTableViewCellDelete <NSObject> -(void)_doAttentionActionDelegate: (UIButton*) sender; @end @interface BOMatchTableViewCell : UITableViewCell { UILabel* lblTitle_;//比赛上部的标题:未开始的比赛显示时间,进行中的比赛显示进行中,已结束的比赛显示已结束 UIImageView* ivTeam1Icon_;//主队队徽 UIImageView* ivTeam2Icon_;//客队队徽 UILabel* lblTeam1Name_;//主队名称 UILabel* lblTeam2Name_;//客队名称 UIButton* btnAttentionIcon_;//未开始比萨显示关注/未关注图标,进行中或已结束比赛显示比分 } @property (nonatomic,strong) BOMatch* match;//比赛 @property (nonatomic,assign) CGFloat height;//cell的实际高度 @property (nonatomic,assign) id<BOMatchTableViewCellDelete> delegate; #pragma mark ----------------> cell的复用或新建 <---------------- +(UITableViewCell*) tableView : (UITableView*) tableView andWithObject : (id) object; @end
BOMatchTableViewCell.m
#import "BOMatchTableViewCell.h" #define WIDTH ScreenWidth //屏幕宽度 #define HEIGHT ScreenHeight //屏幕高度 #define top_to_title_space_height 10 //最顶部与标题的空白高度 #define title_width 80 //比赛上部的标题的宽度 #define title_height 30 //比赛上部的标题的高度 #define title_to_icon_space_height 5 //比赛上部标题与队徽之间的空白高度 #define team1_icon_x 10 //主队队徽x坐标 #define team_icon_to_name_space_width 5 //队徽与名称之间的空白宽度 #define team_name_width 100 //主队/客队名称宽度 #define team_name_height 30 //主队/客队名称高度 #define icon_width 30 // 队徽宽度 #define icon_height 30 // 队徽高度 #define attention_icon_width 20 //关注/未关注icon的宽度 ,必须<=icon_width #define attention_icon_height 20 //关注/未关注icon的高度,必须<=icon_height #define attention_icon_yes KGQ_IMAGE_ATTENTION_YES //关注icon #define attention_icon_no KGQ_IMAGE_ATTENTION_NO //未关注icon #define attention_state_yes 1 //已关注状态值 #define attention_state_no 0 //未关注状态值 #define team_name_font_size 12 //球队名称字体大小 #define title_font_size 13 //标题字体大小 #define match_state_not_start 0 //比赛状态:尚未开始 #define match_state_going 1 //比赛状态:进行中 #define match_state_finish 2 //比赛状态:已结束 #define match_state_going_text @"进行中" //比赛状态为进行中的显示文字 #define match_state_finish_text @"已结束" //比赛状态为已结束的显示文字 #define score_font_size 18 //比分字体大小 @implementation BOMatchTableViewCell - (void)awakeFromNib { } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; } -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ self=[super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { [self _init]; } return self; } #pragma mark ----------------> 初始化操作区 <---------------- -(void)_init{ [self _initSubView]; } -(void)_initSubView{ //比赛上部的标题 lblTitle_=[[UILabel alloc]init]; lblTitle_.font = [UIFont systemFontOfSize:title_font_size]; [self.contentView addSubview:lblTitle_]; //主队头像 ivTeam1Icon_ = [[UIImageView alloc] init]; [self.contentView addSubview:ivTeam1Icon_]; //主队名称 lblTeam1Name_=[[UILabel alloc]init]; lblTeam1Name_.font=[UIFont systemFontOfSize:team_name_font_size]; [self.contentView addSubview:lblTeam1Name_]; //客队头像 ivTeam2Icon_ = [[UIImageView alloc] init]; [self.contentView addSubview:ivTeam2Icon_]; //客队名称 lblTeam2Name_=[[UILabel alloc]init]; lblTeam2Name_.font=[UIFont systemFontOfSize:team_name_font_size]; [self.contentView addSubview:lblTeam2Name_]; //未开始比赛显示关注/未关注图标,进行中或已结束比赛显示比分 btnAttentionIcon_=[UIButton buttonWithType:UIButtonTypeCustom]; btnAttentionIcon_.titleLabel.font=[UIFont systemFontOfSize:score_font_size]; [btnAttentionIcon_ setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [self.contentView addSubview:btnAttentionIcon_]; } #pragma mark ----------------> 填充数据 <---------------- -(void) setMatch:(BOMatch *)match{ //比赛上部的标题:未开始的比赛显示时间,进行中的比赛显示进行中,已结束的比赛显示已结束 NSString* strTitle; NSInteger state =match.matchState; switch (state) { case match_state_not_start: strTitle=[match.time substringWithRange:NSMakeRange(11, 5)]; break; case match_state_going: strTitle=match_state_going_text; break; default: strTitle=match_state_finish_text; break; } CGSize sizeLblTitle = [strTitle sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:title_font_size]}]; CGRect rectLblTitle = CGRectMake(WIDTH/2-sizeLblTitle.width/2, top_to_title_space_height, sizeLblTitle.width, sizeLblTitle.height); lblTitle_.frame=rectLblTitle; lblTitle_.text=strTitle; CGFloat yLblTitle = CGRectGetMaxY(rectLblTitle); //主队头像 [MyHttpRequest downloadImage:match.team1Icon andWithImageShower:ivTeam1Icon_ andWithPlaceHoldIMage:[UIImage imageNamed:KGQ_DEFAULT_FOR_USER] andBlock:^(UIImage *image) {}]; CGRect rectIvTeam1Icon = CGRectMake(team1_icon_x, yLblTitle+title_to_icon_space_height, icon_width, icon_height); ivTeam1Icon_.frame=rectIvTeam1Icon; //主队名称 CGSize sizeLblTeam1Name = [match.team1Name sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:team_name_font_size]}]; CGRect rectLblTeam1Name = CGRectMake(team1_icon_x+icon_width+team_icon_to_name_space_width, yLblTitle+title_to_icon_space_height+(icon_height-sizeLblTeam1Name.height)/2, sizeLblTeam1Name.width, sizeLblTeam1Name.height); lblTeam1Name_.frame=rectLblTeam1Name; lblTeam1Name_.text=match.team1Name; //客队头像 [MyHttpRequest downloadImage:match.team2Icon andWithImageShower:ivTeam2Icon_ andWithPlaceHoldIMage:[UIImage imageNamed:KGQ_DEFAULT_FOR_USER] andBlock:^(UIImage *image) {}]; CGRect rectIvTeam2Icon = CGRectMake(ScreenWidth-team1_icon_x-icon_width, yLblTitle+title_to_icon_space_height, icon_width, icon_height); ivTeam2Icon_.frame=rectIvTeam2Icon; //客队名称 CGSize sizeLblTeam2Name = [match.team2Name sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:team_name_font_size]}]; CGRect rectLblTeam2Name = CGRectMake(ScreenWidth-team1_icon_x-icon_width-team_icon_to_name_space_width-sizeLblTeam2Name.width, yLblTitle+title_to_icon_space_height+(icon_height-sizeLblTeam2Name.height)/2, sizeLblTeam2Name.width, sizeLblTeam2Name.height); lblTeam2Name_.frame=rectLblTeam2Name; lblTeam2Name_.text=match.team2Name; //未开始比赛显示关注/未关注图标,进行中或已结束比赛显示比分 CGRect rectBtnAttentionIcon; switch (state) { case match_state_not_start://未开始比赛显示关注/未关注图标 { NSString* attentionIconName; if(match.attentionState==1){ attentionIconName=attention_icon_yes; }else{ attentionIconName=attention_icon_no; } [btnAttentionIcon_ setTitle:@"" forState:UIControlStateNormal]; [btnAttentionIcon_ setImage:[UIImage imageNamed:attentionIconName] forState:UIControlStateNormal]; rectBtnAttentionIcon = CGRectMake(ScreenWidth/2-attention_icon_width/2, yLblTitle+title_to_icon_space_height+(icon_height-attention_icon_height)/2, attention_icon_width, attention_icon_height); [btnAttentionIcon_ addTarget:self action:@selector(_doAttentionAction:) forControlEvents:UIControlEventTouchUpInside]; break; } default://进行中或已结束比赛显示比分 { NSString* score = [NSString stringWithFormat:@"%ld:%ld",match.team1Score,match.team2Score]; CGSize sizeBtnAttentionIcon = [score sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:score_font_size]}]; [btnAttentionIcon_ setTitle:score forState:UIControlStateNormal]; [btnAttentionIcon_ setImage:nil forState:UIControlStateNormal]; rectBtnAttentionIcon = CGRectMake(ScreenWidth/2-sizeBtnAttentionIcon.width/2, yLblTitle+title_to_icon_space_height+(icon_height-sizeBtnAttentionIcon.height)/2, sizeBtnAttentionIcon.width, sizeBtnAttentionIcon.height); [btnAttentionIcon_ removeTarget:self action:@selector(_doAttentionAction:) forControlEvents:UIControlEventTouchUpInside]; break; } } btnAttentionIcon_.frame=rectBtnAttentionIcon; //高度 self.height=CGRectGetMaxY(ivTeam1Icon_.frame); } #pragma mark ----------------> 关注/取消关注事件 <---------------- -(void)_doAttentionAction: (UIButton*) sender { if ([self.delegate respondsToSelector:@selector(_doAttentionActionDelegate:)]) { [self.delegate _doAttentionActionDelegate:sender]; } } #pragma mark ----------------> cell的复用或新建 <---------------- +(UITableViewCell*) tableView : (UITableView*) tableView andWithObject : (id) object { BOMatch* match = (BOMatch*)object; static NSString* reuseIdentifier = @"cell-BOMatch"; BOMatchTableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier]; if (!cell) { cell = [[BOMatchTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]; } [cell setMatch:match]; return cell; } @end
3.准备UITableView的数据源
这一步就不贴具体代码了,根据实际情况具体准备。
4.将上面1、2、3整合起来实现列表界面
整合的主要代码如下:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ BOMacthShowGroup* group = self.mDataSource[indexPath.section]; id object = group.matchs[indexPath.row]; if ([object isKindOfClass:[BOMatch class]]) {//比赛自定义cell BOMatch* match = (BOMatch*)object; UITableViewCell* cell = [BOMatchTableViewCell tableView:tableView andWithObject:match]; ((BOMatchTableViewCell*)cell).delegate=self; return cell; }else {//联赛自定义cell BOMatchClub* club = (BOMatchClub*)object; return [BOMatchClubTableViewCell tableView:tableView andWithObject:club]; } }
上面代码中就实现了根据不同的业务模型调用不同的自定义UITableViewCell ,从而展示不同的布局。