I am using the code below to put together my UITableView. The Cell height allows the first three rows to show in the table without scrolling. Everything is fine with those first three rows. But as soon as I scroll down past the original first three rows, the image in the myImage inherits the width of cells in the first three rows and does not resize according to the value extracted from the array based on indexPath.row.
The cell is obviously being reused from the else statement from the originally painted cells but I need to figure out a way to allow the myImage width to vary for each row.
Any help is Greatly Appreciated! lq
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
const NSInteger LABEL_TAG = 1001;
const NSInteger IMAGE_TAG = 1002;
UILabel *myLabel;
UIImageView *myImage;
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [myTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// Create the cell
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier]
autorelease];
// Constant values
const CGFloat LABEL_HEIGHT = 20;
const CGFloat LABEL_WIDTH = 140;
const CGFloat LABEL_INDENT = 1;
const CGFloat LABEL_TOP = 0.065 * myTableView.rowHeight;
// Create the label;
myLabel = [[[UILabel alloc] initWithFrame:
CGRectMake(
LABEL_INDENT,
LABEL_TOP + LABEL_HEIGHT,
LABEL_WIDTH,
LABEL_HEIGHT)]
autorelease];
[cell.contentView addSubview:myLabel];
// Configure the label
myLabel.tag = LABEL_TAG;
myLabel.backgroun开发者_开发问答dColor = [UIColor clearColor];
myLabel.textColor = [UIColor blueColor];
myLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize] - 3];
myLabel.textAlignment = UITextAlignmentRight;
// Create the image (NOTE: THIS IS THE PROBLEMATIC PART)
// Extract the width for the image based on an array value for each row:
int xValue = [[myArray objectAtIndex:(indexPath.row)]intValue];
float xLength = (float)xValue / 100;
myImage = [[[UIImageView alloc] initWithFrame:
CGRectMake(
LABEL_INDENT + 53, // This places the image to the right of the label
LABEL_TOP + LABEL_HEIGHT,
xLength * LABEL_WIDTH,
// This is where the width of each row is adjusted LABEL_HEIGHT] autorelease];
[cell.contentView addSubview:myImage];
myImage.contentMode = UIViewContentModeLeft;
myImage.image = [UIImage imageNamed:@"ProgressBar.png"];
myImage.clipsToBounds = YES;
} else {
// Re-use cells
myLabel = (UILabel *)[cell viewWithTag:LABEL_TAG];
myImage = (UIImageView *)[cell viewWithTag:IMAGE_TAG];
}
return cell;
}
The above reuses the cells, as you draw attention to in your comments, but; after finding a cached cell you do the setup again, not matter if the cell is old or new.
The UITableViewCell is a "two-parter", the first time a cell is referenced it is instantiated and build, all the subsequent times it is referenced it should only be updated. (a cell is referenced each time it is scrolled onto the screen or the tableview is reloaded etc. this happens often so to save CPU time it is also best not to do the same setup again and again).
So, try approaching it like this instead:
- (void) configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
UILabel *settingText = [ISInterfaceElement getLabel:Headline]; //Opps... ISInterfaceElement is my custom class. All it does is return a UILabel with settings that comply for a Headline label, according to an enum in the header.
[settingText setFrame:CGRectMake(0.0f, 15.0f, 320.0f, 20.0f)];
[settingText setTextAlignment:UITextAlignmentCenter];
[settingText setTag:SETTINGS_LABEL];
[cell addSubview:settingText];
UIView *background = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 50.0f)];
[cell addSubView:background]; //added
[background release]; //added
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
[self configureCell:cell atIndexPath:indexPath];
}
[(UILabel*)[cell viewWithTag:SETTINGS_LABEL] setText:@"Settings…"];
return cell;
}
So the cellForRowAtIndexPath call the configureCell method if it needs a new cell setup, else it simply updates the cell with the correct value from the model (usually [someArray objectAtIndex:indexPath.row] but in my case just a string.
So send along any parameter(height) you need the configureCell method to know to be able to build your cell, and do all the building in that method and all the updating in cellForRowAtIndex.
Hope it makes sense:)
精彩评论