iOS中的UITableView自定義Cell(模仿新浪微博)

 

 

定義一個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

  • 對於單行文本數據的顯示調用- (CGSize)sizeWithAttributes:(NSDictionary *)attrs;方法來獲得文本寬度和高度。 
  • 對於多行文本數據的顯示調用- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context ;方法來獲得文本寬度和高度;同時注意在此以前須要設置文本控件的numberOfLines屬性爲0。 
  • 一般咱們會在自定義Cell中設置一個高度屬性,用於外界方法調用,由於Cell內部設置Cell的高度是沒有用的,UITableViewCell在初始化時會從新設置高度。

 

 

最後咱們看一下自定義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/

相關文章
相關標籤/搜索