A Closer Look at Table-View Cells


Using Cell Objects in Predefined Styles
typedef enum {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
} UITableViewCellStyle;

1.The UITableViewCell class definesproperties for cell content in these predefined cell styles:
- textLabel—The main label for text in the cell (a UILabel object)
- detailTextLabel—The secondary label for text in the cell when there is additional detail (a UILabel object)
- imageView—An image view to hold an image (a UIImageView object)
For the image-view property, you can also set an alternate image for when the cell is highlighted using thehighlightedImage property of the UIImageView class.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSDictionary *item = (NSDictionary *)[self.content objectAtIndex:indexPath.row];
cell.textLabel.text = [item objectForKey:@"mainTitleKey"];
cell.detailTextLabel.text = [item objectForKey:@"secondaryTitleKey"];
NSString *path = [[NSBundle mainBundle] pathForResource:[item objectForKey:@"imageKey"] ofType:@"png"];
UIImage *theImage = [UIImage imageWithContentsOfFile:path];
cell.imageView.image = theImage;
return cell;
}
2.
When you configure a UITableViewCell object, you also can set various other properties including (but not limited to) the following:
- selectionStyle—Controls the appearance of the cell when selected.(color)
- accessoryType and accessoryView—Allows you to set one of the standard accessory views (disclosure indicator or detail disclosure control) or a custom accessory view for a cell in normal (non-editing) mode.
- editingAccessoryType and editingAccessoryView—Allows you to set one of the standard accessory views (disclosure indicator or detail disclosure control) or a custom accessory view for a cell in editing mode.
- showsReorderControl—Specifies whether it shows a reordering control when in editing mode. The related but read-onlyeditingStyle property specifies the type of editing control the cell has (if any). The delegate returns the value of theeditingStyle property in its implementation of thetableView:editingStyleForRowAtIndexPath: method.
- backgroundView and selectedBackgroundView—Provides a background view (when a cell is unselected and selected) to display behind all other views of the cell.
- indentationLevel and indentationWidth—Specifies the indentation level for cell content and the width of each indentation level.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0 || indexPath.row%2 == 0) {
UIColor *altCellColor = [UIColor colorWithWhite:0.7 alpha:0.1];
cell.backgroundColor = altCellColor;
}
}
Customizing Cells
You have two alternatives to customize your cell. You can add subviews to thecontentView property of the cell object or you can create a custom subclass ofUITableViewCell.
- You should add subviews to a cell’s content view when your content layout can be specified entirely with the appropriate autoresizing settings and when you don’t need to modify the default behavior of the cell.
- You should create a custom subclass when your content requires custom layout code or when you need to change the default behavior of the cell, such as in response to editing mode.
Programmatically Adding Subviews to a Cell’s Content View

Listing 5-3 Adding subviews to a cell’s content view
#define MAINLABEL_TAG 1
#define SECONDLABEL_TAG 2
#define PHOTO_TAG 3
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"ImageOnRightCell";
UILabel *mainLabel, *secondLabel;
UIImageView *photo;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 220.0, 15.0)] autorelease];
mainLabel.tag = MAINLABEL_TAG;
mainLabel.font = [UIFont systemFontOfSize:14.0];
mainLabel.textAlignment = UITextAlignmentRight;
mainLabel.textColor = [UIColor blackColor];
mainLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:mainLabel];
secondLabel = [[[UILabel alloc] initWithFrame:CGRectMake(0.0, 20.0, 220.0, 25.0)] autorelease];
secondLabel.tag = SECONDLABEL_TAG;
secondLabel.font = [UIFont systemFontOfSize:12.0];
secondLabel.textAlignment = UITextAlignmentRight;
secondLabel.textColor = [UIColor darkGrayColor];
secondLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:secondLabel];
photo = [[[UIImageView alloc] initWithFrame:CGRectMake(225.0, 0.0, 80.0, 45.0)] autorelease];
photo.tag = PHOTO_TAG;
photo.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:photo];
} else {
mainLabel = (UILabel *)[cell.contentView viewWithTag:MAINLABEL_TAG];
secondLabel = (UILabel *)[cell.contentView viewWithTag:SECONDLABEL_TAG];
photo = (UIImageView *)[cell.contentView viewWithTag:PHOTO_TAG];
}
NSDictionary *aDict = [self.list objectAtIndex:indexPath.row];
mainLabel.text = [aDict objectForKey:@"mainTitleKey"];
secondLabel.text = [aDict objectForKey:@"secondaryTitleKey"];
NSString *imagePath = [[NSBundle mainBundle] pathForResource:[aDict objectForKey:@"imageKey"] ofType:@"png"];
UIImage *theImage = [UIImage imageWithContentsOfFile:imagePath];
photo.image = theImage;
return cell;
}
Loading Custom Table-View Cells From Nib Files
The Technique for Dynamic Row Content

Listing 5-4 Defining an outlet for the cell
@interface TVController : UITableViewController {
UITableViewCell *tvCell;
}
@property (nonatomic, assign) IBOutlet UITableViewCell *tvCell;
@end
Listing 5-5 Loading a cell from a nib file and assigning it content
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:@"TVCell" owner:self options:nil];
cell = tvCell;
self.tvCell = nil;
}
UILabel *label;
label = (UILabel *)[cell viewWithTag:1];
label.text = [NSString stringWithFormat:@"%d", indexPath.row];
label = (UILabel *)[cell viewWithTag:2];
label.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row];
return cell;
}
The Technique for Static Row Content

Listing 5-6 Defining outlet properties for the cells in the nib file
@interface MyTableViewController : UITableViewController {
UITableViewCell *cell0;
UITableViewCell *cell1;
UITableViewCell *cell2;
UILabel *cell2Label;
}
@property (nonatomic, retain) IBOutlet UITableViewCell *cell0;
@property (nonatomic, retain) IBOutlet UITableViewCell *cell1;
@property (nonatomic, retain) IBOutlet UITableViewCell *cell2;
@property (nonatomic, retain) IBOutlet UILabel *cell2Label;
- (IBAction)logHello;
- (IBAction)sliderValueChanged:(UISlider *)slider;
@end
Listing 5-7 Passing nib-file cells to the table view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return cell0;
}
// section 1
if (indexPath.row == 0) {
return cell1;
}
return cell2;
}
Subclassing UITableViewCell

Before you write the first line of subclassing code, carefully consider some design aspects and performance constraints of UITableViewCell subclasses.
- Draw the entire cell only when appropriate. Your subclass of UITableViewCell could draw all of its content in its drawRect: method, but you should be aware of the potential drawbacks of this approach. Custom drawing applies to the cell’s layer, which can be obscured by any views placed over it.
- Avoid transparency. Always use opaque subviews if at all possible.
- Mark the cell as needing display when viewable properties change.
Listing 5-9 Declaring the properties and methods of the TimeZoneCell class
@class TimeZoneWrapper;
@class TimeZoneView;
@interface TimeZoneCell : UITableViewCell {
TimeZoneView *timeZoneView;
}
@property (nonatomic, retain) TimeZoneView *timeZoneView;
- (void)setTimeZoneWrapper:(TimeZoneWrapper *)newTimeZoneWrapper;
- (void)redisplay;
@end
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]) {
CGRect tzvFrame = CGRectMake(0.0, 0.0, self.contentView.bounds.size.width,
self.contentView.bounds.size.height);
timeZoneView = [[TimeZoneView alloc] initWithFrame:tzvFrame];
timeZoneView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:timeZoneView];
}
return self;
}
Listing 5-11 Declaring the interface of the TimeZoneView class
@interface TimeZoneView : UIView {
TimeZoneWrapper *timeZoneWrapper;
NSDateFormatter *dateFormatter;
NSString *abbreviation;
BOOL highlighted;
BOOL editing;
}
@property (nonatomic, retain) TimeZoneWrapper *timeZoneWrapper;
@property (nonatomic, retain) NSDateFormatter *dateFormatter;
@property (nonatomic, retain) NSString *abbreviation;
@property (nonatomic, getter=isHighlighted) BOOL highlighted;
@property (nonatomic, getter=isEditing) BOOL editing;
@end
- (void)setTimeZoneWrapper:(TimeZoneWrapper *)newTimeZoneWrapper {
// If the time zone wrapper changes, update the date formatter and abbreviation string.
if (timeZoneWrapper != newTimeZoneWrapper) {
[timeZoneWrapper release];
timeZoneWrapper = [newTimeZoneWrapper retain];
[dateFormatter setTimeZone:timeZoneWrapper.timeZone];
NSString *string = [[NSString alloc] initWithFormat:@"%@ (%@)", timeZoneWrapper.abbreviation, timeZoneWrapper.gmtOffset];
self.abbreviation = string;
[string release];
}
[self setNeedsDisplay];
}
Listing 5-13 Drawing the custom table-view cell
- (void)drawRect:(CGRect)rect {
// set up #define constants and fonts here ...
// set up text colors for main and secondary text in normal and highlighted cell states...
CGRect contentRect = self.bounds;
if (!self.editing) {
CGFloat boundsX = contentRect.origin.x;
CGPoint point;
CGFloat actualFontSize;
CGSize size;
// draw main text
[mainTextColor set];
// draw time-zone locale string
point = CGPointMake(boundsX + LEFT_COLUMN_OFFSET, UPPER_ROW_TOP);
[timeZoneWrapper.timeZoneLocaleName drawAtPoint:point forWidth:LEFT_COLUMN_WIDTH withFont:mainFont minFontSize:MIN_MAIN_FONT_SIZE actualFontSize:NULL lineBreakMode:UILineBreakModeTailTruncation baselineAdjustment:UIBaselineAdjustmentAlignBaselines];
// ... other strings drawn here...
// draw secondary text
[secondaryTextColor set];
// draw the time-zone abbreviation
point = CGPointMake(boundsX + LEFT_COLUMN_OFFSET, LOWER_ROW_TOP);
[abbreviation drawAtPoint:point forWidth:LEFT_COLUMN_WIDTH withFont:secondaryFont minFontSize:MIN_SECONDARY_FONT_SIZE actualFontSize:NULL lineBreakMode:UILineBreakModeTailTruncation baselineAdjustment:UIBaselineAdjustmentAlignBaselines];
// ... other strings drawn here...
// Draw the quarter image.
CGFloat imageY = (contentRect.size.height - timeZoneWrapper.image.size.height) / 2;
point = CGPointMake(boundsX + RIGHT_COLUMN_OFFSET, imageY);
[timeZoneWrapper.image drawAtPoint:point];
}
}
Listing 5-14 Returning an initialized instance of the custom table-view cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"TimeZoneCell";
TimeZoneCell *timeZoneCell = (TimeZoneCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (timeZoneCell == nil) {
timeZoneCell = [[[TimeZoneCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
timeZoneCell.frame = CGRectMake(0.0, 0.0, 320.0, ROW_HEIGHT);
}
Region *region = [displayList objectAtIndex:indexPath.section];
NSArray *regionTimeZones = region.timeZoneWrappers;
[timeZoneCell setTimeZoneWrapper:[regionTimeZones objectAtIndex:indexPath.row]];
return timeZoneCell;
本文详细介绍了如何使用UITableView来实现数据展示的定制化,包括使用预定义样式、自定义子视图、从 nib 文件加载自定义单元格以及通过子类化UITableViewCell来实现更复杂的布局和功能。同时,文章提供了在不同场景下调整单元格外观和行为的策略,旨在提高应用的用户体验。
492

被折叠的 条评论
为什么被折叠?



