A comprehensive analysis of the methods of customizing UITableViewCell in IOS applications _ios

Source: Internet
Author: User
Tags uikit

Sometimes we need to define our own UITableViewCell style, which is actually adding a child view to the row. There are two main ways to add a child view: Using code and loading from a. xib file. Of course, the latter method is more intuitive.

First, basic usage
this time we're going to customize a cell so it's like a line on the QQ buddy list: The left is a picture, and the right side of the picture is a three-line label:

Of course, we're not going to get so complicated, just a little bit of fun.

1, run Xcode 4.2, create a new single View application, named Custom Cell:

2, the picture resources into the project. To this end, I looked for 14 50x50. PNG pictures, followed by the name 1, 2 、......、 14, in a folder named images. Drag this folder to the project and select Copy items into in the pop-up window ...

Upon completion of the addition, the engineering directory is as follows:

3, create a UITableViewCell subclass: Select the custom cell directory, select File-new-new File in turn, in the pop-up window, the left Choice cocoa touch, the right choice Objective-c class:

Click Next to enter the class name Customcell,subclass of select UITableViewCell:

After selecting Next and create, two files are created: CustomCell.h and CUSTOMCELL.M.

4, create customcell.xib: Select File-new-new File in turn, in the pop-up window, the left Select User Interface, the right choice empty:

Click Next, select the iphone, click Next, enter the name Customcell, and choose a good location:

Click Create, which creates the customcell.xib.

5, open customcell.xib, drag a table View cell control to the panel:

Select the newly added control, open the Identity Inspector, select Class as Customcell, and then open the size Inspector and adjust the height to 60.

6. Add controls to the newly added table View cell: Drag and drop a ImageView control to the left and set the size to 50x50. Then add three labels to the right of the ImageView, set the label size, the Top 14, and the remaining two 12:

Next, add a outlet mapping to CustomCell.h, mapping ImageView with three labels, named ImageView, Namelabel, Declabel, and loclable, respectively, for Avatar, nickname, personality signature, Place.

Select the table View Cell, open the attribute Inspector, and set the identifier to Customcellidentifier:

In order to fully use these tags, but also to create some of their own data, exist in the plist file, will do behind.

7, open CustomCell.h, add properties:

Copy Code code as follows:

@property (copy, nonatomic) UIImage *image;
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *dec;
@property (copy, nonatomic) NSString *loc;

8, open CUSTOMCELL.M, add code to it:

8.1 Add code below @implementation:

Copy Code code as follows:

@synthesize image;
@synthesize name;
@synthesize Dec;
@synthesize Loc;

8.2 Add code before @end:
Copy Code code as follows:

-(void) SetImage: (UIImage *) img {
if (![ IMG Isequal:image]) {
Image = [img copy];
Self.imageView.image = image;
}
}

-(void) SetName: (NSString *) n {
if (![ N Isequaltostring:name]) {
name = [n copy];
Self.nameLabel.text = name;
}
}

-(void) Setdec: (NSString *) d {
if (![ D Isequaltostring:dec]) {
DEC = [d copy];
Self.decLabel.text = Dec;
}
}

-(void) Setloc: (NSString *) L {
if (![ L Isequaltostring:loc]) {
LOC = [l copy];
Self.locLabel.text = loc;
}
}


This is equivalent to rewriting each set function so that when an assignment operation is performed, the function we write is executed.

Well, now that the cell you've defined is ready to use.

But before we do that, we'll create a new plist to store the data we want to display. The method of establishing the Plist file is mentioned in the previous article. We built a friendsinfo.plist. Add the following data:

Note Each node type selection.

9, open viewcontroller.xib, drag a table view to view, and the delegate and DataSource point to file ' Owner, as described in the previous article.

10, open ViewController.h, add code to it:

Copy Code code as follows:

#import <UIKit/UIKit.h>
@interface Viewcontroller:uiviewcontroller<uitableviewdelegate, uitableviewdatasource>
@property (Strong, nonatomic) Nsarray *datalist;
@property (Strong, nonatomic) Nsarray *imagelist;
@end

11, open VIEWCONTROLLER.M, add code:

11.1 Add in Header:

Copy Code code as follows:

#import "CustomCell.h"

11.2 Add code after @implementation:
Copy Code code as follows:

@synthesize dataList;
@synthesize imageList;

11.3 Adding code to the Viewdidload method:
Copy Code code as follows:

-(void) viewdidload
{
[Super Viewdidload];
Do no additional setup after loading the view, typically from a nib.
Load data and pictures for plist files
NSBundle *bundle = [NSBundle mainbundle];
Nsurl *plisturl = [Bundle urlforresource:@ "Friendsinfo" withextension:@ "plist"];

Nsdictionary *dictionary = [Nsdictionary Dictionarywithcontentsofurl:plisturl];

Nsmutablearray *tmpdataarray = [[Nsmutablearray alloc] init];
Nsmutablearray *tmpimagearray = [[Nsmutablearray alloc] init];
for (int i=0; i<[dictionary count]; i++) {
NSString *key = [[NSString alloc] initwithformat:@ "%i", i+1];
Nsdictionary *tmpdic = [dictionary Objectforkey:key];
[Tmpdataarray Addobject:tmpdic];

NSString *imageurl = [[NSString alloc] initwithformat:@ "%i.png", i+1];
UIImage *image = [UIImage imagenamed:imageurl];
[Tmpimagearray Addobject:image];
}
Self.datalist = [Tmpdataarray copy];
Self.imagelist = [Tmpimagearray copy];
}

11.4 Adding code to the Viewdidunload method:
Copy Code code as follows:

Self.datalist = nil;
Self.imagelist = nil;

11.5 Add code before @end:
Copy Code code as follows:

#pragma mark-
#pragma mark Table Data Source Methods
-(Nsinteger) TableView: (UITableView *) TableView numberofrowsinsection: (nsinteger) Section {
return [self.datalist Count];
}

-(UITableViewCell *) TableView: (UITableView *) TableView Cellforrowatindexpath: (Nsindexpath *) IndexPath {
static NSString *customcellidentifier = @ "Customcellidentifier";

static BOOL nibsregistered = NO;
if (!nibsregistered) {
uinib *nib = [uinib nibwithnibname:@ "Customcell" bundle:nil];
[TableView registernib:nib Forcellreuseidentifier:customcellidentifier];
nibsregistered = YES;
}

Customcell *cell = [TableView dequeuereusablecellwithidentifier:customcellidentifier];


Nsuinteger row = [Indexpath row];
Nsdictionary *rowdata = [Self.datalist objectatindex:row];

Cell.name = [RowData objectforkey:@ "name"];
Cell.dec = [RowData objectforkey:@ "Dec"];
Cell.loc = [RowData objectforkey:@ "Loc"];
Cell.image = [ImageList objectatindex:row];

return cell;
}

#pragma mark Table Delegate Methods
-(CGFloat) TableView: (UITableView *) TableView Heightforrowatindexpath: (Nsindexpath *) Indexpath {
return 60.0;
}

-(Nsindexpath *) TableView: (UITableView *) TableView
Willselectrowatindexpath: (Nsindexpath *) Indexpath {
return nil;
}


12. Operation:

Second, how to reuse UITableViewCell

The purpose of reuse is to reduce memory consumption, if there are 1000 cell, if not reused, then each slide must be again

Alloc a lot of cell, consumes memory, at the same time the screen will appear discontinuous phenomenon, shake eyes.

Reusing a cell is simple, when you create a cell, you use the

Alloc Initwithtableviewcellstyle:reuseidentifer This interface to create a cell instance rather than using Alloc initwithframe

Using the former means that the cell can be reused, identifer using a fixed nsstring can

The code is as follows:

Copy Code code as follows:

-(uitableviewcell*) TableView: (UITableView *) TableView Cellforrowatindexpath: (Nsindexpath *) IndexPath
{
static NSString *cellidentifier = @ "Cell";
UITableViewCell *cell = [TableView dequeuereusablecellwithidentifier:cellidentifier];//first pops a cell from a reusable queue
if (cell = = nil) {//Description reusable queue inside and cell, you need to re-create the cell instance, using the following method
cell = [[UITableViewCell alloc] Initwithstyle:uitableviewcellstyledefault reuseidentifier:cellidentifier];
}else{//now indicates a reusable cell, which can be returned directly
NSLog (@ "cell reuse");
}
return cell;
}

How to adjust the height of the cell dynamically?
This problem is still more headaches, the following function is sure to use
Copy Code code as follows:

-(CGFloat) TableView: (UITableView *) TableView Heightforrowatindexpath: (Nsindexpath *) Indexpath

After practice, it is found that the frame can be set when creating a cell or reusing a cell

such as Cell.frame=cgrectmake (0,0,320,450);

This code works, and in the following function

Use:

Copy Code code as follows:

-(CGFloat) TableView: (UITableView *) TableView Heightforrowatindexpath: (Nsindexpath *) Indexpath
{

NSLog (@ "is currently%ld row", (long) indexpath.row);

UITableViewCell *mycell=[self Tableview:tableview cellforrowatindexpath:indexpath];//Gets the cell instance in the current IndexPath
if (MyCell = = nil) {
return 0;

}else{

NSLog (@ "%f", myCell.frame.size.height);
return myCell.frame.size.height;

}
return 0;

}

The cell instance above obtaining the current Indexpath will reapply for an instance (meaning a cell actually creates two instances)
The purpose of this is to get the frame of the cell, and if you do not do so, you can save the cell frame in a private

Variable, access to this private variable in Heightforrowatindexpath

The above method can dynamically change the height of UITableViewCell

Iv. for a uilabel, calculate the CGRect according to its content

First, you set the font for uilable, such as

Tmlabel.font=[uifont systemfontofsize:14.0f];

Then use Boundingrectofsize to calculate the size of the rectangle corresponding to this size, the code is as follows:

Copy Code code as follows:

Nsdictionary *attrdic=@{nsfontattributename:[uifont systemfontofsize:12.0f]};
Cgsize Labelsize=[text Boundingrectwithsize:cgsizemake (320, 990)
options:nsstringdrawinguseslinefragmentorigin| Nsstringdrawingusesfontleading
Attributes:attrdic context:nil].size;

CGRect labelrect=cgrectmake (0, 0, labelsize.width, labelsize.height);

Now that the rect of uilable can be computed, if a UITableViewCell is customized and its internal uilabel height is variable,
can also be achieved.

V. Uilabel with variable height inside the UITableViewCell
If there are other controls, such as UIButton and so on, it is the same.

These controls, when instantiated, set the frame to Cgrectzero, and then calculate their respective heights and dimensions respectively.

Add these subspaces to the cell using the Cell.contentview Addsubview method. When the cell frame is recalculated

You also need to add the frame of these controls. Code on:

Copy Code code as follows:

-(uitableviewcell*) TableView: (UITableView *) TableView Cellforrowatindexpath: (Nsindexpath *) IndexPath
{

static NSString *cellidentifier = @ "Cell";
UITableViewCell *cell = [TableView dequeuereusablecellwithidentifier:cellidentifier];

if (cell = = nil) {
cell = [[UITableViewCell alloc] Initwithstyle:uitableviewcellstyledefault reuseidentifier:cellidentifier];

Uilabel *label = [[Uilabel alloc] Initwithframe:cgrectzero];
Label.tag = 1;
Label.linebreakmode = nslinebreakbycharwrapping;
Label.highlightedtextcolor = [Uicolor Whitecolor];
Label.numberoflines = 0;
Label.opaque = NO; Select opaque to indicate that nothing behind the view should be drawn
Label.font=[uifont systemfontofsize:12.0f];
Label.backgroundcolor = [Uicolor Graycolor];
[Cell.contentview Addsubview:label];

UIButton *tmpbutton=[[uibutton Alloc]initwithframe:cgrectzero];
tmpbutton.tag=2;
Tmpbutton.backgroundcolor=[uicolor Cyancolor];
[Cell.contentview Addsubview:tmpbutton];
Tmpbutton.opaque=no;
[Tmpbutton settitle:@ "Nihao" forstate:uicontrolstatenormal];
[Tmpbutton settitlecolor:[uicolor Whitecolor]forstate:uicontrolstatehighlighted];
[Tmpbutton addtarget:self Action: @selector (Tmpbuttonhandler:) forcontrolevents:uicontroleventtouchupinside];

}else{
NSLog (@ "cell reuse");
}

Uilabel *tmplabel= (Uilabel *) [cell viewwithtag:1];
NSString *text=[tmparray ObjectAtIndex:indexPath.row];
Tmplabel.text=text;

UIButton *tmpbutton= (UIButton *) [cell viewwithtag:2];

Nsdictionary *attrdic=@{nsfontattributename:[uifont systemfontofsize:12.0f]};
Cgsize Labelsize=[text Boundingrectwithsize:cgsizemake (320, 990)
options:nsstringdrawinguseslinefragmentorigin| Nsstringdrawingusesfontleading
Attributes:attrdic context:nil].size;

CGRect labelrect=cgrectmake (0, 0, labelsize.width, labelsize.height);//Calculate Uilabel rect
[Tmplabel Setframe:labelrect];
[Tmpbutton setframe:cgrectmake (0, labelsize.height+1, 100, 50)];//compute UIButton for rect child controls
[Cell setframe:cgrectmake (0, 0, labelsize.width, labelsize.height+50+1)];//cell frame is the sum of the above two child controls

return cell;
}

Why set the frame when it is no longer created, but behind the IF and else logic?
When you reuse a cell, the cell that is removed from the Reuse cell queue, and its contents (Uilabel) is the previous cell content, needs to repopulate the Uilabel and recalculate

The frame of the entire cell and sets its frame. When you create a cell, you also need to set the frame, so the two logics are repeated and placed directly outside of the if else logic.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.