服务器之家

服务器之家 > 正文

iOS App开发中使用及自定义UITableViewCell的教程

时间:2021-01-16 14:54     来源/作者:张智清

uitableview用来以表格的形式显示数据。关于uitableview,我们应该注意:

(1)uitableview用来显示表格的可见部分,uitableviewcell用来显示表格的一行。

(2)uitableview并不负责存储表格中的数据,而是仅仅存储足够的数据使得可以画出当前可见部分。

(3)uitableview从uitableviewdelegate协议获取配置信息,从uitableviewdatasource协议获得数据信息。

(4)所有的uitableview实现时实际上只有一列,但是我们可以通过向uitableviewcell中添加子视图,使得它看起来有好几列。

(5)uitableview有两种风格:

    ① grouped:每一组看起来像是圆矩形;
    ② plain:这是默认风格,可以修改成indexed风格。
   
uitableviewcell使用实例
在下边的小例子中,我们将先实现显示一列数据,然后在每行添加图像,之后再看看uitableviewcell的四种分别是什么样的。最后再进行其他操作,比如设置缩进、修改字体大小和行高等。

1、运行xcode 4.2,新建一个single view application,名称为table sample:

iOS App开发中使用及自定义UITableViewCell的教程

2、单击viewcontroller.xib,使用interface builder给视图添加一个uitableview控件,并使其覆盖整个视图:

iOS App开发中使用及自定义UITableViewCell的教程

3、选中新添加的uitableview控件,打开connection inspector,找到delegate和datasource,从它们右边的圆圈拉线到file's owner图标:

iOS App开发中使用及自定义UITableViewCell的教程

4、单击viewcontroller.h,在其中添加代码:

复制代码 代码如下:

#import <uikit/uikit.h>
@interface viewcontroller : uiviewcontroller<uitableviewdelegate, uitableviewdatasource>
@property (strong, nonatomic) nsarray *listdata;
@end


5、单击viewcontroller.m,在其中添加代码:

 

5.1 在@implementation后面添加代码:

复制代码 代码如下:

@synthesize listdata;


5.2 在viewdidload方法中添加代码:

复制代码 代码如下:

- (void)viewdidload
{
    [super viewdidload];
    // do any additional setup after loading the view, typically from a nib.
    nsarray *array = [[nsarray alloc] initwithobjects:@"tree", @"flower",
                      @"grass", @"fence", @"house", @"table", @"chair",
                      @"book", @"swing" , nil];
    self.listdata = array;
}


5.3 在viewdidunload方法中添加代码:

复制代码 代码如下:

- (void)viewdidunload
{
    [super viewdidunload];
    // release any retained subviews of the main view.
    // e.g. self.myoutlet = nil;
    self.listdata = nil;
}


5.4 在@end之前添加代码:

复制代码 代码如下:


#pragma mark -
#pragma mark table view data source methods
//返回行数
- (nsinteger)tableview:(uitableview *)tableview
 numberofrowsinsection:(nsinteger)section {
    return [self.listdata count];
}

 

//新建某一行并返回
- (uitableviewcell *)tableview:(uitableview *)tableview
         cellforrowatindexpath:(nsindexpath *)indexpath {
   
    static nsstring *tablesampleidentifier = @"tablesampleidentifier";
   
    uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier:
                             tablesampleidentifier];
    if (cell == nil) {
        cell = [[uitableviewcell alloc]
                initwithstyle:uitableviewcellstyledefault
                reuseidentifier:tablesampleidentifier];
    }
   
    nsuinteger row = [indexpath row];
    cell.textlabel.text = [listdata objectatindex:row];
 return cell;
}


上面的第二个方法中,

复制代码 代码如下:

uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier: tablesampleidentifier];


这个语句根据标识符tablesampleidentifier寻找当前可以重用的uitableviewcell。当某行滑出当前可见区域后,我们重用它所对应的uitableviewcell对象,那么就可以节省内存和时间。
如果执行词语后,cell为nil,那我们再创建一个,并设置去标识符为tablesampleidentifier:

复制代码 代码如下:

cell = [[uitableviewcell alloc] initwithstyle:uitableviewcellstyledefault reuseidentifier:tablesampleidentifier];


这里uitableviewcellstyledefault是表示uitableviewcell风格的常数,除此之外,还有其他风格,后面将会用到。
注意参数(nsindexpath *)indexpath,它将行号row和部分号section合并了,通过[indexpath row];获取行号。之后给cell设置其文本:

复制代码 代码如下:

cell.textlabel.text = [listdata objectatindex: row];


6、运行一下:

 

iOS App开发中使用及自定义UITableViewCell的教程

7、给每一行添加图片:
7.1 将图片资源添加到工程:拖到工程中,前面的文章有提到。
7.2 在cellforrowatindexpath方法的return语句之前添加代码:

复制代码 代码如下:

uiimage *image = [uiimage imagenamed:@"blue.png"];
cell.imageview.image = image;
uiimage *highlighedimage = [uiimage imagenamed:@"yellow.png"];
cell.imageview.highlighedimage = highlighedimage;


7.3 运行,效果如下:

 

iOS App开发中使用及自定义UITableViewCell的教程

可以看到,每行左边都出现一张图片。当选中某行,其图片改变。

8、设置行的风格:
表示uitableviewcell风格的常量有:

复制代码 代码如下:

uitableviewcellstyledefault
uitableviewcellstylesubtitle
uitableviewcellstylevalue1
uitableviewcellstylevalue2


这几种风格的区别主要体现在image、text label以及detail text label。
为了体现风格,在cellforrowatindexpath方法的return语句之前添加代码:

复制代码 代码如下:

cell.detailtextlabel.text = @"detail text";


然后将

复制代码 代码如下:

cell = [[uitableviewcell alloc] initwithstyle:uitableviewcellstyledefault reuseidentifier:tablesampleidentifier];


中的uitableviewcellstyledefault依次换成上面提到的四个风格常量,并运行,效果分别如下:

 

iOS App开发中使用及自定义UITableViewCell的教程

uitableviewcellstyledefault  

iOS App开发中使用及自定义UITableViewCell的教程

uitableviewcellstylesubtitle

iOS App开发中使用及自定义UITableViewCell的教程

uitableviewcellstylevalue1

iOS App开发中使用及自定义UITableViewCell的教程

uitableviewcellstylevalue2
    
9、设置缩进:

将所有行的风格改回uitableviewcellstyledefault,然后在@end之前添加代码如下:

复制代码 代码如下:

#pragma mark table delegate methods
- (nsinteger)tableview:(uitableview *)tableview indentationlevelforrowatindexpath:(nsindexpath *)indexpath {
    nsuinteger row = [indexpath row];
    return row;
}


这里将第row行缩进row,如下图所示:

 

iOS App开发中使用及自定义UITableViewCell的教程

10、操纵行选择:
在@end之前添加代码:

复制代码 代码如下:

- (nsindexpath *)tableview:(uitableview *)tableview willselectrowatindexpath:(nsindexpath *)indexpath {
    nsuinteger row = [indexpath row];
    if (row%2 == 0) {
        return nil;
    }
    return indexpath;
}


上面的方法在选择某行之前执行,我们可以在这个方法中添加我们想要的操作。这里,我们实现的是,如果选择的行号(从0开始计)是偶数,则取消选择。
在@end之前添加代码:

复制代码 代码如下:

- (void)tableview:(uitableview *)tableview didselectrowatindexpath:(nsindexpath *)indexpath {
    nsuinteger row = [indexpath row];
    nsstring *rowvalue = [listdata objectatindex:row];
   
    nsstring *message = [[nsstring alloc] initwithformat:
                         @"you selected %@", rowvalue];
    uialertview *alert = [[uialertview alloc]
                          initwithtitle:@"row selected!"
                          message:message
                          delegate:nil
                          cancelbuttontitle:@"yes i did"
                          otherbuttontitles:nil];
    [alert show];
    [tableview deselectrowatindexpath:indexpath animated:yes];
}


当选择某行之后,就弹出一个alert,用来显示我们所做的选择。
运行一下,你会发现第0、2等行无法选择。选择奇数行时会弹出提示:

 

iOS App开发中使用及自定义UITableViewCell的教程

而且关闭提示框后,选择的那行也被取消了选择,用的语句

复制代码 代码如下:

[tableview deselectrowatindexpath:indexpath animated:yes];


11、设置字体大小和表格行高:
11.1 在cellforrowatindexpath方法中的return之前添加代码,用于设置字体和大小:

复制代码 代码如下:

cell.textlabel.font = [uifont boldsystemfontofsize:50];


11.2 在@end之前添加代码,用于设置行高:

复制代码 代码如下:

- (cgfloat)tableview:(uitableview *)tableview heightforrowatindexpath:(nsindexpath *)indexpath {
    return 70;
}


运行,看看效果:

 

iOS App开发中使用及自定义UITableViewCell的教程

 

可任意自定义的uitableviewcell
uitableview的强大更多程度上来自于可以任意自定义uitableviewcell单元格。通常,uitableview中的cell是动态的,在使用过程中,会创建一个cell池,根据每个cell的高度(即tableview:heightforrowatindexpath:返回值),以及屏幕高度计算屏幕中可显示几个cell。而进行自定义tableviewcell无非是采用代码实现或采用ib编辑nib文件来实现两种方式,本文主要收集代码的方式实现各种cell自定义。
1.如何动态调整cell高度

复制代码 代码如下:


- (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath {
 
    static nsstring *cellidentifier = @"cell";
 
    uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier:cellidentifier];
    if (cell == nil) {
        cell = [[[uitableviewcell alloc] initwithframe:cgrectzero reuseidentifier:cellidentifier] autorelease];
        uilabel *label = [[uilabel alloc] initwithframe:cgrectzero];
        label.tag = 1;
        label.linebreakmode = uilinebreakmodewordwrap;
        label.highlightedtextcolor = [uicolor whitecolor];
        label.numberoflines = 0;
        label.opaque = no; // 选中opaque表示视图后面的任何内容都不应该绘制
        label.backgroundcolor = [uicolor clearcolor];
        [cell.contentview addsubview:label];
        [label release];
    }
 
    uilabel *label = (uilabel *)[cell viewwithtag:1];
    nsstring *text;
    text = [textarray objectatindex:indexpath.row];
    cgrect cellframe = [cell frame];
    cellframe.origin = cgpointmake(0, 0);
 
    label.text = text;
    cgrect rect = cgrectinset(cellframe, 2, 2);
    label.frame = rect;
    [label sizetofit];
    if (label.frame.size.height > 46) {
        cellframe.size.height = 50 + label.frame.size.height - 46;
    }
    else {
        cellframe.size.height = 50;
    }
    [cell setframe:cellframe];
 
    return cell;
}

 

- (cgfloat)tableview:(uitableview *)tableview heightforrowatindexpath:(nsindexpath *)indexpath
{
    uitableviewcell *cell = [self tableview:tableview cellforrowatindexpath:indexpath];
    return cell.frame.size.height;
}


2.如何用图片自定义table separeator分割线
一般地,利用类似[tableview setseparatorcolor:[uicolor redcolor]];语句即可修改cell中间分割线的颜色。那又如何用一个图片作为分割线背景呢?可以尝试如下:
方法一:
先设置cell separatorcolor为clear,然后把图片做的分割线添加到自定义的custom cell上。

 

方法二:
在cell里添加一个像素的imageview后将图片载入进,之后设置tableview.separatorstyle = uitableviewcellseparatorstylenone

3.自定义首行cell与其上面导航栏间距

复制代码 代码如下:

tableview.tableheaderview = [[[uiview alloc] initwithframe:cgrectmake(0,0,5,20)] autorelease];


4.自定义uitableviewcell的accessory样式
默认的accessorytype属性有四种取值:uitableviewcellaccessorynone、uitableviewcellaccessorydisclosureindicator、uitableviewcellaccessorydetaildisclosurebutton、uitableviewcellaccessorycheckmark。如果想使用自定义附件按钮的其他样式,则需使用uitableview的accessoryview属性来指定。

复制代码 代码如下:

uibutton *button;
if(iseditableornot) {
    uiimage *image = [uiimage imagenamed:@"delete.png"];
    button = [uibutton buttonwithtype:uibuttontypecustom];
    cgrect frame = cgrectmake(0.0,0.0,image.size.width,image.size.height);
    button.frame = frame;
    [button setbackgroundimage:image forstate:uicontrolstatenormal];
    button.backgroundcolor = [uicolor clearcolor];
    cell.accessoryview = button;
}else{
    button = [uibutton buttonwithtype:uibuttontypecustom];
    button.backgroundcolor = [uicolor clearcolor];
    cell.accessoryview = button;
}


以上代码仅仅是定义了附件按钮两种状态下的样式,问题是现在这个自定义附件按钮的事件仍不可用。即事件还无法传递到uitableviewdelegate的accessorybuttontappedforrowwithindexpath方法上。当我们在上述代码中在加入以下语句:

复制代码 代码如下:
[button addtarget:self action:@selector(btnclicked:event:) forcontrolevents:uicontroleventtouchupinside];


后,虽然可以捕捉到每个附件按钮的点击事件,但我们还无法进行区别到底是哪一行的附件按钮发生了点击动作!因为addtarget:方法最多允许传递两个参数:target和event,这两个参数都有各自的用途了(target指向事件委托对象,event指向所发生的事件)。看来只依靠cocoa框架已经无法做到了。

 

      但我们还是可以利用event参数,在自定义的btnclicked方法中判断出事件发生在uitableview的哪一个cell上。因为uitableview有一个很关键的方法indexpathforrowatpoint,可以根据触摸发生的位置,返回触摸发生在哪一个cell的indexpath。而且通过event对象,正好也可以获得每个触摸在视图中的位置。

复制代码 代码如下:

// 检查用户点击按钮时的位置,并转发事件到对应的accessory tapped事件
- (void)btnclicked:(id)sender event:(id)event
{
     nsset *touches = [event alltouches];
     uitouch *touch = [touches anyobject];
     cgpoint currenttouchposition = [touch locationinview:self.tableview];
     nsindexpath *indexpath = [self.tableview indexpathforrowatpoint:currenttouchposition];
     if(indexpath != nil)
     {
         [self tableview:self.tableview accessorybuttontappedforrowwithindexpath:indexpath];
     }
}


这样,uitableview的accessorybuttontappedforrowwithindexpath方法会被触发,并且获得一个indexpath参数。通过这个indexpath参数,我们即可区分到底哪一行的附件按钮发生了触摸事件。

复制代码 代码如下:

- (void)tableview:(uitableview *)tableview accessorybuttontappedforrowwithindexpath:(nsindexpath *)indexpath
{
    int  *idx = indexpath.row;
   //这里加入自己的逻辑
}
标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
Intellij idea2020永久破解,亲测可用!!!
Intellij idea2020永久破解,亲测可用!!! 2020-07-29
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享 2020-04-07
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
返回顶部