Question

I have a custom UITableViewCell which contains several UIButtons. Each button's frame position is relative to the cell width. I set autoresizingMask=UIViewAutoresizingFlexibleWidth so it will adjust the cell width and the button positions properly when the application starts with the device either in landscape or portrait mode.

The issue is when the device is rotated from one mode to the other, the buttons do not adjust positions because the UITableViewCell is reusable. In other words, the cell is not initialized based on the new UITalbeView width because the cell's function initWithStyle is called before the device is rotated and is not called again after the device rotation. Any suggestions?

Was it helpful?

Solution 2

After spending hours of research (including posts in this site), I could not find any solutions. But a light bulb turns on all of a sudden. The solution is very simple. Just detect whether the device orientation is landscape or portrait mode and define the ReusableCellIdentifier with a different name for each.

static NSString*Identifier;

if ([UIDevice currentDevice].orientation!=UIDeviceOrientationLandscapeLeft && [UIDevice currentDevice].orientation!=UIDeviceOrientationLandscapeRight) {
                Identifier= @"aCell_portrait";
            }
            else Identifier= @"DocumentOptionIdentifier_Landscape";


    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];

OTHER TIPS

Since UITableViewCell is also a UIView, you can override setFrame method. Everytime that your table view rotates, this method will be called for all cells.

-(void)setFrame:(CGRect)frame
{
    [super setFrame:frame];

    //Do your rotation stuffs here :)
} 

Previous answer has a serious problem. You should use [UIApplication sharedApplication].statusBarOrientation instead of [UIDevice currebtDevice].orientation because Device orientation has nothing to do with interface orientation - Device orientation is physical rotation based on accelerometer.

The ticked answer works like a charm in old iOS versions. For iOS 6.0 I used the next code:

static NSString *Identifier;
if (self.interfaceOrientation==UIInterfaceOrientationPortrait) {
    Identifier=@"aCell_portrait";
}
else {
    Identifier=@"DocumentOptionIdentifier_Landscape";
}

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];

You'll need to fix your cells frame width (assuming the height is same in portrait and landscape mode) within your cellForRowAtIndexPath method. That is what is working here. I used to create a custom TableViewCell with IB and it is always initialised for portrait 320 px width. With defining the frame it works as expected, even if the cell is "reused" from queue.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 ...
 UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
 if (cell == nil) {
    // create cell here...
 }

 // Adjust cell frame width to be equal to tableview frame width
 cell.frame = CGRectMake(0, 0, tableView.frame.size.width, cell.frame.size.height);
 ...
}

I had a similar problem and this post helped me. In my case I have a custom class declared in a separate file, and in this file I have the following code in layoutSubviews:

//PORTRAIT CELL
if ([UIDevice currentDevice].orientation!=UIDeviceOrientationLandscapeLeft && 
    [UIDevice currentDevice].orientation!=UIDeviceOrientationLandscapeRight)
{
    //build the custom content views for portrait mode here
}
else
{
    //build the custom content views for landscape mode here
}

Then in my view controller I just implement willAnimateRotationToInterfaceOrientation: and send the reloadData message to my table view.

With this I don't have to touch the cellForRow method.

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