Question

I have a custom UITableViewCell which contains a UILabel. I'm trying to dynamically resize the width of the UILabel to correctly show the text it contains. I know how to resize the UILabel, but I'm noticing some strange behavior in the way that the UITableViewCell resizes the UILabel when using an accessoryType of UITableViewCellAccessoryDisclosureIndicator. The cell is setup as follows:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, 145, 31)];
label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin;
label.backgroundColor = [UIColor blueColor]; // So that I can see the frame
[cell.contentView addSubview:label];

Then I have a typical cellForRowAtIndexPath implementation as follows:

- (UITableViewCell *)tableView:(UITableView *)_table_view cellForRowAtIndexPath:(NSIndexPath *)_index_path
{
    static NSString *cell_id = @"Cell";
    CustomTableViewCell *cell = (CustomTableViewCell *)[_table_view dequeueReusableCellWithIdentifier:cell_id];

    if(!cell)
    {
        cell = [[[CustomTableViewCell alloc] initWithReuseIdentifier:cell_id] autorelease];
    }

    // Resize UILabel frame.  Note: assume that CustomTableViewCell has label property
    cell.label.frame = CGRectMake(15, 0, 290, 31);
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.editingAccessoryType = UITableViewCellAccessoryDisclosureIndicator;

    return(cell);
}

Everything is fine when the CustomTableViewCell is allocated for the first time. Even though the width of the UILabel is 290, it gets shrunk down to fit appropriately in the cell because the cell needs room to display disclosure indicator. The problem occurs when I switch away from the table view (such as switching to a different tab, etc). When I come back to the table view the CustomTableViewCell doesn't get allocated because it is returned from the dequeueReusableCellWithIdentifier function. When the UILabel gets resized by setting the frame, the cell no longer seems to respect the fact that the UILabel should be resized to fit within the disclosure indicator and results in the UILabel overlapping the disclosure indicator.

It seems that when the following conditions are present, the UITableViewCell doesn't correct auto resize the subviews:

  1. Working with a UITableViewCell returned from dequeueReusableCellWithIdentifier
  2. Resize a UIView which is a subview of contentView by setting the frame
  3. UITableViewCell is using UITableViewCellAccessoryDisclosureIndicator as an accessory.

Does anybody have an idea why this could be happening and a way to get around it? Thanks!

Was it helpful?

Solution

What is happening is that both the UILabel and the contentView (which is the UILabel's parent/super view) are being resized smaller to compensate for the disclosure indicator accessory after cellForRowAtIndexPath is called. That is why the first time the cell is displayed, everything was working fine. I had set the width of the UILabel to 290 in cellForRowAtIndexPath and then the UILabel resized from 290 to a smaller amount to fit correctly at some point after cellForRowAtIndexPath was called.

The next time the cell gets displayed and is retrieved from the dequeueReusableCellWithIdentifier function it had already had the disclosure indicator from before and therefore, was already resized smaller. When I reset the width to 290 again, it never resized to fit because the disclosure indicator was already present. Because of that, the UILabel was too large.

Basically, I need to size the UILabel relative to the size of it's parent view (contentView) instead of using a static value of 290. That way if the cell hasn't been resized yet (which is the case the first time the cell is to be displayed) it will be resized appropriately. If the cell has already been resized so will the parent view so setting the UILabel width based on contentView will produce the desired behavior.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top