定義一個KCStatusTableViewCell實現UITableViewCell,通常實現自定義UITableViewCell須要分爲兩步:第一初始化控件;第二設置數據,從新設置控件frame。緣由就是自定義Cell通常沒法固定高度,不少時候高度須要隨着內容改變。此外因爲在單元格內部是沒法控制單元格高度的,所以通常會定義一個高度屬性用於在UITableView的代理事件中設置每一個單元格高度。app
首先看一下微博模型KCStatus,這個模型主要的方法就是根據plist字典內容生成微博對象:佈局
KCStatus.h字體
#import <Foundation/Foundation.h> //微博模型KCStatus,這個模型主要的方法就是根據plist字典內容生成微博對象: @interface KCStatus : NSObject #pragma mark - 屬性 @property (nonatomic,assign) long long Id;//微博ID @property (nonatomic,copy) NSString *profileImageUrl;//用戶頭像 @property (nonatomic,copy) NSString *userName;//用戶名稱 @property (nonatomic,copy) NSString *mbtype;//會員類型 @property (nonatomic,copy) NSString *createdAt;//建立時間 @property (nonatomic,copy) NSString *source;//設備來源 @property (nonatomic,copy) NSString *text;//微博內容 #pragma mark - 方法 #pragma mark 根據字典初始化微博對象 -(KCStatus *)initWithDictionary:(NSDictionary *)dic; #pragma mark 初始化微博對象(靜態方法) +(KCStatus *)statusWithDictionary:(NSDictionary *)dic; @end
KCStatus.mui
#import "KCStatus.h" @implementation KCStatus #pragma mark 根據字典初始化微博對象 -(KCStatus *)initWithDictionary:(NSDictionary *)dic{ if (self = [super init]) { self.Id = [dic[@"id"] longLongValue]; self.profileImageUrl = dic[@"profileImageUrl"]; self.userName = dic[@"userName"]; self.mbtype = dic[@"mbtype"]; self.createdAt = dic[@"createdAt"]; self.source = dic[@"source"]; self.text = dic[@"text"]; } return self; } #pragma mark 初始化微博對象(靜態方法) +(KCStatus *)statusWithDictionary:(NSDictionary *)dic{ KCStatus *status = [[KCStatus alloc]initWithDictionary:dic]; return status; } //使用 stringWithFormat 拼接設備來源 -(NSString *)source{ return [NSString stringWithFormat:@"來自 %@", _source]; } @end
而後看一下自定義的Cellatom
KCStatusTableViewCell.hspa
#import <UIKit/UIKit.h> //#import "KCStatus.h" // import會包含這個類的全部信息,包括實體變量和方法,而@class只是告訴編譯器,其後面聲明的名稱是類的名稱,至於這些類是如何定義的,暫時不用考慮,後面會再告訴你。 @class KCStatus; //自定義的cell @interface KCStatusTableViewCell : UITableViewCell #pragma mark 微博對象 @property (nonatomic, strong) KCStatus *status; #pragma mark 單元格高度 @property (assign, nonatomic) CGFloat height; @end
KCStatusTableViewCell.m代理
#import "KCStatusTableViewCell.h" #import "KCStatus.h" #define KCColor(r,g,b) [UIColor colorWithHue:r/255.0 saturation:g/255.0 brightness:b/255.0 alpha:1] //顏色宏定義 #define kStatusTableViewCellControlSpacing 10 //控件間距 #define kStatusTableViewCellBackgroundColor KCColor(251,251,251) #define kStatusGrayColor KCColor(50,50,50) #define kStatusLightGrayColor KCColor(120,120,120) #define kStatusTableViewCellAvatarWidth 40 //頭像寬度 #define kStatusTableViewCellAvatarHeight kStatusTableViewCellAvatarWidth #define kStatusTableViewCellUserNameFontSize 14 #define kStatusTableViewCellMbTypeWidth 13 //會員圖標寬度 #define kStatusTableViewCellMbTypeHeight kStatusTableViewCellMbTypeWidth #define kStatusTableViewCellCreateAtFontSize 12 #define kStatusTableViewCellSourceFontSize 12 #define kStatusTableViewCellTextFontSize 14 @interface KCStatusTableViewCell(){ UIImageView *cellAvatar;//用戶頭像 UIImageView *cellMbType;//會員類型 UILabel *cellUserName;//用戶名稱 UILabel *cellCreateAt;//建立時間 UILabel *cellSource;//設備來源 UILabel *cellText;//微博內容 } @end @implementation KCStatusTableViewCell -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { [self initSubView]; } return self; } #pragma mark 初始化視圖 -(void)initSubView{ //頭像控件 cellAvatar = [[UIImageView alloc]init]; [self.contentView addSubview:cellAvatar]; //用戶名 cellUserName = [[UILabel alloc]init]; cellUserName.textColor = kStatusGrayColor; cellUserName.font = [UIFont systemFontOfSize:kStatusTableViewCellUserNameFontSize]; [self.contentView addSubview:cellUserName]; //會員類型 cellMbType = [[UIImageView alloc]init]; [self.contentView addSubview:cellMbType]; //日期 cellCreateAt = [[UILabel alloc]init]; cellCreateAt.textColor = kStatusLightGrayColor; cellCreateAt.font = [UIFont systemFontOfSize:kStatusTableViewCellCreateAtFontSize]; [self.contentView addSubview:cellCreateAt]; //設備 cellSource = [[UILabel alloc]init]; cellSource.textColor = kStatusLightGrayColor; cellSource.font = [UIFont systemFontOfSize:kStatusTableViewCellSourceFontSize]; [self.contentView addSubview:cellSource]; //內容 cellText = [[UILabel alloc]init]; cellText.textColor = kStatusGrayColor; cellText.font = [UIFont systemFontOfSize:kStatusTableViewCellTextFontSize]; cellText.numberOfLines=0; // cellText.lineBreakMode=NSLineBreakByWordWrapping; [self.contentView addSubview:cellText]; } #pragma mark 設置微博 -(void)setStatus:(KCStatus *)status{ //設置頭像大小和位置 CGFloat avatarX=10,avatarY=10; CGRect avatarRect=CGRectMake(avatarX, avatarY, kStatusTableViewCellAvatarWidth, kStatusTableViewCellAvatarHeight); cellAvatar.image=[UIImage imageNamed:status.profileImageUrl]; cellAvatar.frame=avatarRect; //設置會員圖標大小和位置 CGFloat userNameX= CGRectGetMaxX(cellAvatar.frame)+kStatusTableViewCellControlSpacing ; CGFloat userNameY=avatarY; //根據文本內容取得文本佔用空間大小 CGSize userNameSize=[status.userName sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:kStatusTableViewCellUserNameFontSize]}]; CGRect userNameRect=CGRectMake(userNameX, userNameY, userNameSize.width,userNameSize.height); cellUserName.text=status.userName; cellUserName.frame=userNameRect; //設置會員圖標大小和位置 CGFloat mbTypeX=CGRectGetMaxX(cellUserName.frame)+kStatusTableViewCellControlSpacing; CGFloat mbTypeY=avatarY; CGRect mbTypeRect=CGRectMake(mbTypeX, mbTypeY, kStatusTableViewCellMbTypeWidth, kStatusTableViewCellMbTypeHeight); cellMbType.image=[UIImage imageNamed:status.mbtype]; cellMbType.frame=mbTypeRect; //設置發佈日期大小和位置 CGSize createAtSize=[status.createdAt sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:kStatusTableViewCellCreateAtFontSize]}]; CGFloat createAtX=userNameX; CGFloat createAtY=CGRectGetMaxY(cellAvatar.frame)-createAtSize.height; CGRect createAtRect=CGRectMake(createAtX, createAtY, createAtSize.width, createAtSize.height); cellCreateAt.text=status.createdAt; cellCreateAt.frame=createAtRect; //設置設備信息大小和位置 CGSize sourceSize=[status.source sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:kStatusTableViewCellSourceFontSize]}]; CGFloat sourceX=CGRectGetMaxX(cellCreateAt.frame)+kStatusTableViewCellControlSpacing; CGFloat sourceY=createAtY; CGRect sourceRect=CGRectMake(sourceX, sourceY, sourceSize.width,sourceSize.height); cellSource.text=status.source; cellSource.frame=sourceRect; //設置微博內容大小和位置 CGFloat textX=avatarX; CGFloat textY=CGRectGetMaxY(cellAvatar.frame)+kStatusTableViewCellControlSpacing; CGFloat textWidth=self.frame.size.width-kStatusTableViewCellControlSpacing*2; CGSize textSize=[status.text boundingRectWithSize:CGSizeMake(textWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:kStatusTableViewCellTextFontSize]} context:nil].size; CGRect textRect=CGRectMake(textX, textY, textSize.width, textSize.height); cellText.text=status.text; cellText.frame=textRect; _height=CGRectGetMaxY(cellText.frame)+kStatusTableViewCellControlSpacing; } - (void)awakeFromNib { // Initialization code } #pragma mark 重寫選擇事件,取消選中 - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } @end
這是咱們自定義Cell這個例子的核心,自定義Cell分爲兩個步驟:首先要進行各類控件的初始化工做,這個過程當中只要將控件放到Cell的View中同時設置控件顯示內容的格式(字體大小、顏色等)便可;而後在數據對象設置方法中進行各個控件的佈局(大小、位置)。在代碼中有幾點須要重點提示你們:code
最後咱們看一下自定義Cell的使用過程:orm
KCStatusViewController.h對象
#import <UIKit/UIKit.h> @interface KCStatusViewController : UIViewController @end
KCStatusViewController.m
#import "KCStatusViewController.h" #import "KCStatus.h" #import "KCStatusTableViewCell.h" @interface KCStatusViewController ()<UITableViewDelegate,UITableViewDataSource,UIAlertViewDelegate>{ UITableView *myTableView; NSMutableArray *statusArray; NSMutableArray *statusCellsArray;//存儲cell,用於計算高度 } @end @implementation KCStatusViewController - (void)viewDidLoad { [super viewDidLoad]; //初始化數據 [self initData]; //建立一個分組樣式的UITableView myTableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; //設置數據源,注意實現UITableViewDataSource協議 myTableView.dataSource = self; //設置代理 myTableView.delegate = self; [self.view addSubview:myTableView]; } #pragma mark 加載數據 -(void)initData{ NSString *path = [[NSBundle mainBundle] pathForResource:@"StatusInfo" ofType:@"plist"]; NSArray *array = [NSArray arrayWithContentsOfFile:path]; statusArray = [[NSMutableArray alloc]init]; statusCellsArray = [[NSMutableArray alloc]init]; [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { [statusArray addObject:[KCStatus statusWithDictionary:obj]]; KCStatusTableViewCell *cell = [[KCStatusTableViewCell alloc]init]; [statusCellsArray addObject:cell]; }]; } #pragma mark - 數據源方法 #pragma mark 返回分組數 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } #pragma mark 返回每組行數 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return statusArray.count; } #pragma mark 返回每行的單元格(cell上面展現的內容) - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *cellIdentifier = @"UITableViewCellIdentifierKey1"; KCStatusTableViewCell *cell; cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (!cell) { cell = [[KCStatusTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; } /** * 這個類中須要重點強調一下:Cell的高度須要從新設置(前面說過不管Cell內部設置多高都沒有用,須要從新設置),這裏採用的方法是首先建立對應的Cell,而後在- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;方法中設置微博數據計算高度通知UITableView。 */ //在此設置微博,以便從新佈局 KCStatus *status = statusArray[indexPath.row]; cell.status = status; return cell; } #pragma mark - 代理方法 #pragma mark 從新設置單元格高度 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ // KCStatusTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; KCStatusTableViewCell *cell = statusCellsArray[indexPath.row]; cell.status = statusArray[indexPath.row]; return cell.height; } #pragma mark 重寫狀態樣式方法 -(UIStatusBarStyle)preferredStatusBarStyle{ return UIStatusBarStyleLightContent; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end
大神地址:http://www.cnblogs.com/kenshincui/