UITableView 系列之自定義 UITableViewCell


本來不打算寫UITableView的,因為網上已經有很多這方面的文章,尤其是 趣味蘋果開發中的TableViewController系列 已經有很詳細的講解了。但是群里還是有很多童鞋會問這方面的問題,所以在這里以自己的理解方式比划一下。

讓我們先來看一張從模擬器截下來的圖:

上圖是一個UITableView列表,紅色的1、2、3、4、5...是一個個的UITableViewCell。

從這張截圖我們可以看出來 UITableView 是由一系列 UITableViewCell 組成的列表,由此我們可以知道 UITableViewCell 在 UITableVeiw 中的重要性了。

在真實地項目中,UITableViewCell 中的各項內容的排列都不同(如上圖4中的 2013年、全國等),它自帶的那幾種樣式根本無法滿足我們的需求,所以這就需要我們來自定義自己的Cell(下文中的Cell都表示UITableViewCell)了。

以上圖中的Cell為例,我們來自定義一個UITableViewCell。首先我們來創建一個應用——CustomTableVeiwCellDemo,打開XCode,選擇File -> New -> Project...,如下圖所示:

然后選擇iOS->Application->Single View Application,然后點Next,如下圖所示:

在Product Name中輸入“CustomTableVeiwCellDemo”,其他設置部分參照下圖:

 

然后點Next,保存到磁盤適當的位置,至此我們的Xcode應該是下圖這個樣子:

工程創建完成了,然后開始我們的UITableView之旅吧。

首先我們需要有一個UITableView,那么我們給上圖中的WViewController.xib上拖拽一個UITableVeiw,然后綁定UITableView的dataSource與delegate到WViewController上,如下圖:

我們給UITableView設置個名稱為tableView

並給WViewController.h 設置 dataSource、delegate的代理,代碼如下:

//
//  WViewController.h
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface WViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>

@property (strong, nonatomic) IBOutlet UITableView *tableView;

@end

然后在WViewController.m中實現dataSource與delegate的部分方法,如 UITableView的區段數、UITableView的行數、指定行的UITableVeiwCell、單擊單元格的處理等

#pragma mark - UITableView methods
/**
 1、返回 UITableView 的區段數
 */
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    
}

/**
 2、返回 UITableView 的行數
 */
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    
}

/**
 3、設置行的高度
 */
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    
}

/**
 4、返回指定的 row 的 cell
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
}

/**
 5、點擊單元格時的處理
 */
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
} 

接下來我們按照上邊注釋的步驟來填充方法

1、本例中我們只需要一個區段,所以返回1就ok了。

/**
 1、返回 UITableView 的區段數
 */
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;      
}

2、要知道返回的行數,首先我們需要知道有多少條數據,到目前為止,我們還沒有定義要顯示的數據,所以先讓我們來定義要顯示在UITableView上的數據吧。

  2.1 我們需要顯示的是年份、省份、標題,所以首先我們定義一個試卷模型WPaperModel,用來存放顯示的這些屬性。

  右鍵工程->New Group,創建一個組Model,

  

  選擇Model,在點擊下圖1的位置,創建一個Model文件夾與之相關聯

  

  在Model里邊添加文件WPaperModel,並添加相應的屬性,並初始化模型對象,代碼如下:

 

  WPaperModel.h

//
//  WPaperModel.h
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//
//  試卷模型
//  

#import <Foundation/Foundation.h>

@interface WPaperModel : NSObject

@property (nonatomic, assign) NSInteger paperID;        // 試卷代號
@property (nonatomic, strong) NSString *paperYear;      // 試卷所屬年份
@property (nonatomic, strong) NSString *paperProvince;  // 試卷所屬省份
@property (nonatomic, strong) NSString *paperTitle;     // 試卷標題

/**
 初始化試卷模型對象
 @param paperId     試卷代號
 @param year        試卷年份
 @param province    試卷省份
 @param title       試卷標題
 */
- (id)initWithPaperID:(NSInteger)paperId
              paperYear:(NSString *)year
          paperProvince:(NSString *)province
             paperTitle:(NSString *)title;

@end

  WPaperModel.m

//
//  WPaperModel.m
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//
//  試卷模型
//

#import "WPaperModel.h"

@implementation WPaperModel

/**
 初始化試卷模型對象
 @param paperId     試卷代號
 @param year        試卷年份
 @param province    試卷省份
 @param title       試卷標題
 */
- (id)initWithPaperID:(NSInteger)paperId
              paperYear:(NSString *)year
          paperProvince:(NSString *)province
             paperTitle:(NSString *)title{
    self = [super init];
    
    if (self) {
        self.paperID        = paperId;
        self.paperYear      = year;
        self.paperProvince  = province;
        self.paperTitle     = title;
    }
    
    return self;
}

@end

  2.2 在WViewController.m中定義要顯示的數據,把這些數據初始化到數據模型中,並把數據模型添加到要展示在UITableView的列表集合中,代碼如下:

  定義數據數組與試卷列表

@interface WViewController (){
    NSArray *_dataArray;        // 數據數組
    NSMutableArray *_paperList; // 試卷列表
}

  初始化數據數組、試卷列表與試卷模型,並把試卷模型添加到試卷列表中

  

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 初始化數據數組
    _dataArray = @[@[@"2013", @"北京", @"2012-2013學年北京市石景山區初一下學期期末考試數學試卷(帶解析)"],
                   @[@"2013", @"江蘇", @"2012-2013學年江蘇蘇州市景范中學初二第二學期期末考試數學試卷(帶解析)"],
                   @[@"2013", @"湖北", @"2013年湖北省恩施州初中數學評價《實數與代數式》單元試卷(一)(帶解析)"],
                   @[@"2013", @"全國", @"2013人教版初中數學七年級上冊第一章有理數練習卷(帶解析)"],
                   @[@"2013", @"湖北", @"2013年初中畢業升學考試(湖北十堰卷)數學(帶解析)"]];
    
    // 初始化試卷列表
    _paperList = [[NSMutableArray alloc]init];
    for (int i=0; i<_dataArray.count; i++) {
        // 初始化試卷模型
        WPaperModel *paperModel = [[WPaperModel alloc]initWithPaperID:i
                                                            paperYear:_dataArray[i][0]
                                                        paperProvince:_dataArray[i][1]
                                                           paperTitle:_dataArray[i][2]];
        // 添加試卷模型到試卷列表中
        [_paperList addObject:paperModel];
    }
}

  2.3 至此我們知道了要展示在UITableView上邊的數據列表為_paperList了,那么也就知道了UITableView的行數了,所以就可以設置行數了

/**
 2、返回 UITableView 的行數
 */
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _paperList.count;
}

3、由於我們要自定義Cell,所以行的高度也就是自定義Cell的高度,接下來我們就自定義Cell,起名為 WPaperCell

  3.1 與上邊2.1類似,先建立一個View組,然后關聯到View文件夾中,再然后在View中創建WPaperCell,如下圖:

  

  3.2 創建完成后,我們為WPaperCell建立相對應的WPaperCell.xib文件,如下圖我們選擇iOS -> Use Interface -> Empty,然后點擊Next

  

  然后拖拽一個UITableViewCell到WPaperCell.xib上,並與WPaperCell類關聯

  

  3.3 給Cell上拖拽3個UILabel,用來顯示年、省份、標題,設置Identifier標識符為paperCell,Accessory的值為Disclosure Indicator,如下圖:

  

  上圖中UILabel的線框,可以參考 iOS 開發問題集錦(二) 中的第2個問題。

  3.4 給3個UILabel設置名稱,並初始化,代碼如下:

  WPaperCell.h

//
//  WPaperCell.h
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//
//  自定義UITableViewCell
//  

#import <UIKit/UIKit.h>
#import "WPaperModel.h"

@interface WPaperCell : UITableViewCell

@property (strong, nonatomic) IBOutlet UILabel *lblYear;        // 年標簽 
@property (strong, nonatomic) IBOutlet UILabel *lblProvince;    // 省份標簽
@property (strong, nonatomic) IBOutlet UILabel *lblTitle;       // 標題標簽

/**
 設置Cell
 */
-(void)setupCell:(WPaperModel *)model;

@end

  WPaperCell.m 

//
//  WPaperCell.m
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//

#import "WPaperCell.h"

@implementation WPaperCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

/**
 設置Cell
 */
-(void)setupCell:(WPaperModel *)model{
    self.lblYear.text       = model.paperYear;
    self.lblProvince.text   = model.paperProvince;
    self.lblTitle.text      = model.paperTitle;
}

@end

  3.5 由於剛自定義的Cell的窗口高度為88,所以設置行高為88

/**
 3、設置行的高度
 */
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 88.0f;
}

4、返回指定的行,由於是自定義的Cell,所以此處需要返回WPaperCell,首先導入 #import "WPaperCell.h",然后設置,這里有兩種設置方式。

  設置方式1:

/**
 4、返回指定的 row 的 cell
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 1. cell標識符,使cell能夠重用
    static NSString *paperCell = @"paperCell";
    
    // 2. 注冊自定義Cell的到TableView中,並設置cell標識符為paperCell
    static BOOL isRegNib = NO;
    if (!isRegNib) {
        [tableView registerNib:[UINib nibWithNibName:@"WPaperCell" bundle:nil] forCellReuseIdentifier:paperCell];
        isRegNib = YES;
    }
    
    // 3. 從TableView中獲取標識符為paperCell的Cell
    WPaperCell *cell = [tableView dequeueReusableCellWithIdentifier:paperCell];
    
    // 4. 設置單元格屬性
    [cell setupCell:_paperList[indexPath.row]];
    
    return cell;
}

  設置方式2:  

/**
 4、返回指定的 row 的 cell
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 1. cell標示符,使cell能夠重用
    static NSString *paperCell = @"paperCell";
    // 2. 從TableView中獲取標示符為paperCell的Cell
    WPaperCell *cell = (WPaperCell *)[tableView dequeueReusableCellWithIdentifier:paperCell];
    // 如果 cell = nil , 則表示 tableView 中沒有可用的閑置cell
    if(cell == nil){
        // 3. 把 WPaperCell.xib 放入數組中
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"WPaperCell" owner:self options:nil] ;
        
        // 獲取nib中的第一個對象
        for (id oneObject in nib){
            // 判斷獲取的對象是否為自定義cell
            if ([oneObject isKindOfClass:[WPaperCell class]]){
                // 4. 修改 cell 對象屬性
                cell = [(WPaperCell *)oneObject initWithStyle:UITableViewCellStyleDefault reuseIdentifier:paperCell];
            }
        }
    }
    // 5. 設置單元格屬性
    [cell setupCell:_paperList[indexPath.row]];
    return cell;
}

 

5、點擊單元格時,輸出省份,代碼如下:

/**
 5、點擊單元格時的處理
 */
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    WPaperModel *paperModel = _paperList[indexPath.row];
    NSLog(@"paper province -> %@", paperModel.paperProvince);
}

OK,大功告成,運行一下,看看效果:

 

代碼傳送門:CustomTableViewCell

 

著作權聲明:本文由 http://wzrong.cnblogs.com 或者 http://iostour.diandian.com 原創,歡迎轉載分享。 請尊重作者勞動,轉載時保留該聲明和作者博客鏈接,謝謝!

 


 

原創文章,如需轉載請注明出處,謝謝!

歡迎訪問本人技術微博 @iOS之旅 相互交流,共同學習,共同進步!

歡迎訪問本人微博 @衛志榮

 

 

 

  

   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM