This question has been asked 100 times on SO, but I'm not able to solve my problem.
I've got two customizable cells. Both can have dynamic heights. My tableView:heightForRowAtIndexPath:
returns the proper height for each cell, but when cells are reused, the separator line between cells isn't in the right spot 100% of the time. I can't use the hack of adding my own line in my cells because sometimes the overlap is so bad you can't click on the right cell.
What do I need to do to make sure it uses the proper height?
Here is an example of the separator line being in the wrong spots (supposed to be right above the title):
Here is how I set my heights:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
InspectionItem *item = [items objectAtIndex:indexPath.row];
int t = [item.rating.ratingType ratingTypeK];
if (t == RatingTypeTextfield){
CGFloat height = [OQCTextFieldCell heightOfCellWithTitle:item.name
subtext:item.descriptionText
text:item.comment
andScreenWidth:self.view.frame.size.width];
return height;
}
else {
CGFloat height = [OQCButtonCell heightOfCellWithTitle:item.name
subtext:item.descriptionText
andScreenWidth:self.view.frame.size.width];
return height;
}
}
Again, these class methods return the proper heights.
Here is how I set my cells up (short version):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
InspectionItem *item = [items objectAtIndex:indexPath.row];
int t = [item.rating.ratingType ratingTypeK];
if (t == RatingTypeTextfield){
static NSString *CellIdentifier = @"TextFieldCell";
OQCTextFieldCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.titleLabel.text = item.name;
...
return cell;
}
else {
static NSString *CellIdentifier = @"ButtonCell";
OQCButtonCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.titleLabel.text = item.name;
...
return cell;
}
}
Here is how I'm registering my cells:
UINib *buttonNib = [UINib nibWithNibName:@"OQCButtonCell" bundle:[NSBundle mainBundle]];
[self.tableView registerNib:buttonNib forCellReuseIdentifier:@"ButtonCell"];
UINib *textFieldNib = [UINib nibWithNibName:@"OQCTextFieldCell" bundle:[NSBundle mainBundle]];
[self.tableView registerNib:textFieldNib forCellReuseIdentifier:@"TextFieldCell"];
UINib *flagNib = [UINib nibWithNibName:@"OQCFlagCell" bundle:[NSBundle mainBundle]];
[self.tableView registerNib:flagNib forCellReuseIdentifier:@"FlagCell"];
My cells only overwrite layoutSubviews
and they do call super first thing.
I need the solution to be good for iOS 5.2+.
Update
Here is my code for layoutSubviews
. I do believe that my custom method heightOfCellWithTitle:subtext:text:
returns the right height since it matches what the layoutSubview
height
variable is at the end of this method.
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat height = 0;
// Title + Header background view
NSString *title = titleLabel.text;
CGRect frame = self.titleLabel.frame;
CGSize size = [title sizeWithFont:titleLabel.font
constrainedToSize:CGSizeMake(frame.size.width, 9999)
lineBreakMode:titleLabel.lineBreakMode];
size.width = frame.size.width; // don't let it shrink
titleLabel.numberOfLines = size.height / titleLabel.font.lineHeight;
frame.size = size;
self.titleLabel.frame = frame;
frame = self.headerBackgroundView.frame;
frame.size.height = size.height + 8;
self.headerBackgroundView.frame = frame;
// single line of text should be 30
height += frame.size.height;
CGRect subContentFrame = subContentView.frame;
subContentFrame.origin.y = height;
CGFloat subHeight = 0;
// Label
title = subtextLabel.text;
if ([title length] > 0){
subHeight += 5; // top margin
size = [title sizeWithFont:subtextLabel.font
constrainedToSize:CGSizeMake(subtextLabel.frame.size.width, 9999) lineBreakMode:subtextLabel.lineBreakMode];
size.width = self.contentView.frame.size.width - 52; // don't let it shrink
subtextLabel.numberOfLines = size.height / subtextLabel.font.lineHeight;
frame = self.subtextLabel.frame;
frame.size = size;
frame.origin.y = subHeight;
self.subtextLabel.frame = frame;
// subtext height + bottom margin
subHeight += size.height + 5;
}
else {
subHeight += 25;
}
// Button
frame = button.frame;
frame.origin.y = subHeight;
button.frame = frame;
subHeight += frame.size.height + 25;
subContentFrame.size.height = subHeight;
subContentView.frame = subContentFrame;
// reposition detailIndicator
frame = self.detailIndicator.frame;
frame.origin.x = subContentView.frame.size.width - 37;
self.detailIndicator.frame = frame;
height += subHeight;
// Drawer
frame = CGRectMake(0, 0, self.frame.size.width, height);
[self.drawerView setFrame:frame];
self.backgroundView = self.drawerView;
}
Also, quick note about the numbers I've been checking.
I have a log on layoutSubviews
and tableView:heightForRowAtIndexPath:
which give me correct heights (I'm basing that off of layoutSubviews
since it is recalculating the height for the entire cell). And then I have a log for tableView:cellForRowAtIndexPath:
which at the end just before I return the cell I print out the cell's height, and it is an old height of a reused view, which I kind of expect. I would assume that after the cell is returned that iOS will recalculate what the position of the cell should be based on tableView:heightForRowAtIndexPath:
and reposition the views with layoutSubviews
.
so if you layout the cells dynamically in the cell class and overwrite layoutSubviews this should be enough in heightForRowAtIndexPath:
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
float height = cell.frame.size.height;
return height;
remember that you have to "reset" all uiviews in your cell to the start values. otherwise the the cell will use the current values, ie if you have a label at y=10 and set it programmatically to y=20, next time the cell is used the cell still have y=20.
Have you tried calling
[cell setNeedsLayout];
[cell layoutIfNeeded];
before returning it?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.