Rotate a custom UITableViewCell
Asked Answered
P

6

7

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?

Palaearctic answered 19/3, 2010 at 12:40 Comment(3)
It ends up the solution is much simpler. It just needs to set self.contentView.autoresizingMask=UIViewAutoresizingFlexibleWidth; self.contentView.autoresizesSubviews=YES; It does NOT work by setting self.autoresizingMask.Palaearctic
I have the same issue as you and was thinking of using specific cell tags for each orientation cases since this idea came to me after thinking a while. Using self.contentView.autoresizesSubviews=YES does not work on my side.Erdrich
Finally I used another trick.Erdrich
P
7

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];
Palaearctic answered 19/3, 2010 at 14:14 Comment(0)
M
13

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 :)
} 
Monadism answered 1/6, 2011 at 19:34 Comment(0)
P
7

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];
Palaearctic answered 19/3, 2010 at 14:14 Comment(0)
U
6

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.

Unaware answered 19/12, 2010 at 20:23 Comment(2)
Thank you for informing about the second option. In fact, both can work. See #2739234Palaearctic
I'm sorry, you are not right. Device orientation has 6 different options, while interface orientation has 4. If your device is laying plain on the table, Device orientation will report "Face Up", which has nothing common at all with current interface orientation.Unaware
S
2

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];
Stargell answered 7/3, 2013 at 14:17 Comment(0)
F
1

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);
 ...
}
Fidelfidela answered 26/12, 2010 at 17:54 Comment(0)
H
0

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.

Hospitalize answered 14/3, 2012 at 0:33 Comment(1)
using the layoutSubviews you don't need to use the reloadData, and it's better if you don't use it, because if you are in edition mode with the delete button shown, and rotate, the delete button will dissapear because of the reloadDataSinegold

© 2022 - 2024 — McMap. All rights reserved.