zoukankan      html  css  js  c++  java
  • 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之旅 相互交流,共同学习,共同进步!

    欢迎访问本人微博 @卫志荣

      

       

  • 相关阅读:
    vue(21)初识Vuex
    ESCMScript6(3)Promise对象
    vue(20)生命周期函数
    vue(19)嵌套路由
    vue(18)路由懒加载
    vue(17)vue-route路由管理的安装与配置
    vue(16)vue-cli创建项目以及项目结构解析
    vue(15)vue-cli介绍与安装
    webpack(11)配置文件分离为开发配置、生成配置和基础配置
    webpack(10)webpack-dev-server搭建本地服务器
  • 原文地址:https://www.cnblogs.com/wzrong/p/3261130.html
Copyright © 2011-2022 走看看