开发者

autoresizing UITableCells contents in Landscape

In a UITableView, I add content to my cells via UILabels.

To define the optimal size (as large as allowed by the cell's width) I noticed that only tableView.contentSize.width was reliable, because cell.contentView.bounds gives always a portrait width, even in landscape

This works very well in couple with autoresizingMask: when I switch from Portrait to Landscape and again to Portrait.

Problems come when I load my View directly in Landscape. The width of my UILabels is larger than the screen, even if a breakpoint shows me a correct width for tableView.contentSize.width

Switching between landscape and portait changes nothing, the width is still larger than the screen.

If I don't use autoresizingMask, the width is correct, if I use it, even with a short text it goes out of the screen (but I notice it only thanks to a test background color or with using very large NSString).

In brief:

  • portrait > landscape > portrait > landscape... is fine (resize perfectly)
  • landscape > portrait > landscape > portrait... bugs (width outrange)

My code simplified:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    //[...]
    UIFont *font = [UIFont fontWithName:@"Helvetica-Bold" size:12.0];
    CGRect frame = CGRectMake(cell.contentView.bounds.origin.x + 20,
                                  cell.contentView.bounds.origin.y + 4,
                                  tableView.contentSize.width - 50,
                                  font.lineHeight);

      //at this point a breakpoint shows that frame is whatever I asked (ex: 200 for test)
      //but still the labels is wider than the screen
    UILabel *result = [开发者_JAVA技巧[[UILabel alloc] initWithFrame:frame] autorelease];
    [result setText:@"bouh!"];
    result.lineBreakMode = UILineBreakModeWordWrap;
    result.numberOfLines = 1;
    result.font = font;

      //if I comment this line, the width is always what I want
    result.autoresizingMask = UIViewAutoresizingFlexibleWidth;

      //test to see the real size
    result.backgroundColor = [UIColor orangeColor];

    [cell.contentView addSubview:result];
    //[...]
    return cell;
}

I'm asking your help here in order to see if there's a better way to do what I wanted? if not, what am I doing wrong?


I could not find a clean easy universal solution (adaptable to every screen).

But here is what I did to make it work:

    //in portrait cell width works fine with autoResize
    //in landscape tableView width works fine with autoResize
CGFloat cellWidth;

if ( [UIDevice currentDevice].orientation != UIDeviceOrientationLandscapeLeft
    && [UIDevice currentDevice].orientation != UIDeviceOrientationLandscapeRight)
  {
    cellWidth = tableView.contentSize.width;
  }
else
  {
    cellWidth = cell.contentView.bounds.size.width;
  }

And so, later in the code I use it that way:

CGRect frame = CGRectMake(cell.contentView.bounds.origin.x + 20,
                                  cell.contentView.bounds.origin.y + 4,
                                  cellWidth - 50,
                                  font.lineHeight);
UILabel *result = [[[UILabel alloc] initWithFrame:frame] autorelease];

But something was weird: I needed to use always tableView.contentSize.width for the frame of my Activity Indicators because cell.contentView.bounds.size.width was only 320 even in Landscape

CGRect activityIndicatorRect =
CGRectMake(
           cell.contentView.bounds.origin.x + tableView.contentSize.width - 60 ,
           cell.contentView.bounds.origin.y + 17,
           30, 30);


What I tend to do is subclass UITableViewCell and then override the initWithReuseIdentifier...

- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier  {        
    self = [super initWithReuseIdentifier:reuseIdentifier];

    if (self != nil) {
        [self setFrame:CGRectMake(0.0, 0.0, kLayoutWidth, kLayoutHeight)];

        // Set up labels, buttons etc....
    }
}

kLayoutWidth and kLayoutHeight are defines you can set to arbitrary values, you can put the values directly in the CGRect but I prefer to have sizes specified at the top of the class as compiler defines.

The beauty of this is that now you can layout your cell in a fixed size and set autoresizing masks for the content elements, and when the tableview resizes the cell it will all resize correctly.


You can also use different nibs for Portrait/Landscape/iPhone/iPad and load them accordingly. Saves you lots of code

static NSString *aCustomCellIdentifier = @"aCustomCell";

CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:aCustomCellIdentifier];

if (!cell)
{
    if (!IS_IPAD)
        cell = [[[UINib nibWithNibName:@"CustomCell" bundle:nil] instantiateWithOwner:self options:nil] lastObject];
    else
        cell = [[[UINib nibWithNibName:@"CustomCell_iPad" bundle:nil] instantiateWithOwner:self options:nil] lastObject];

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜