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];
}
精彩评论