Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recalculating subview sizes on rotation in iOS 7

I have a method I call to calculate the sizes of a bunch of labels I have in a custom UITableViewCell subclass, which is in a UIPopoverController. When the user rotates the device, I need to recalculate the sizes, and then have the table re-drawn to use the new sizes. Every method I've tried to detect the rotation is either depreciated, doesn't get called, or doesn't get called at the right time. Is there a method that will automatically get called when the device is rotated that I can recalculate my sizes in?


Edit: What I have tried and why it doesn't work:

  • shouldAutorotate - doesn't get called - apparently depreciated.
  • layoutSubviews - gets called, but if I try to [self.tableView reloadData] in here, I get stuck in an infinite loop
  • NSNotificationCenter observer for UIDeviceOrientationDidChangeNotification - Gets called before my controller knows it's new dimensions, so I cannot recalculate my sizes here
  • [self.tableView setNeedsDisplay] in layoutSubviews - doesn't prompt re-drawing of table.
  • didRotateFromInterfaceOrientation - doesn't get called - apparently depreciated.

Edit 2: More details on what I'm trying to do

I'm trying to imitate a "rows-and-columns" style table, and line up the labels to imitate the columns. When I recalculate the sizes, I loop through all the rows of the table, then through each "column" in that row. I get the width of each column, and keep track of the largest width in all the rows for each column. Then I manipulate the spacing between widths and the font sizes to get it so that if any row has the widest label in every column, it will still fit on the screen.

like image 891
GeneralMike Avatar asked Nov 02 '22 12:11

GeneralMike


2 Answers

You don't want to rely on the actual rendered UILabels inside of your cell to calculate your "column" widths. Do this instead:

  1. Implement a method called calculateColumnWidthsForInterfaceOrientation: that takes an UIInterfaceOrientation. In that method, check if the requested orientation is portrait or landscape using UIInterfaceOrientationIsLandscape(orientation). Then, based on the orientation go through the data you want to display in your labels and find the widest column widths using NSString's sizeWithAttributes: method (or one of its derivatives). Caches those values in an array or something.
  2. Add a method like setColumnWidths: to your custom table view cell that takes the desired column widths.
  3. In your tableView:cellForRowAtIndexPath: method, retrieve the cached column widths and set it on the cell using the setColumnWidths: method.
  4. In your cell, layout the labels using the column widths you just set.
  5. In your view controller, implement didRotateFromInterfaceOrientation:. Inside of it, call calculateColumnWidthsForInterfaceOrientation: with the given orientation and after that call [self.tableView reloadData].
  6. Finally, in viewDidLoad, call [self calculateColumnWidthsForInterfaceOrientation:self.interfaceOrientation] to do the initial setup of your data before the first rotation.

That should do the trick.

Update: The total width of your cell should be equal to the total width of your table view. That can be managed with auto-layout or by other means. That size will be reflected in the cell's frame size.

Update 2: Since we are talking about a popover, you could maybe simply dismiss the popover in willRotateToInterfaceOrientation:duration: and then display it again with your new desired dimensions after the rotation is done in didRotateFromInterfaceOrientation:.

like image 162
Johannes Fahrenkrug Avatar answered Nov 12 '22 18:11

Johannes Fahrenkrug


in layoutSubviews try to recalculate subview one cell

for example in CustomCell.m

- (void)layoutSubviews
{

UIViewController *viewController = (id)[(AppDelegate *)[UIApplication sharedApplication].delegate window].rootViewController;

if (UIInterfaceOrientationIsPortrait(viewController.interfaceOrientation))
    self.backgroundColor = [UIColor redColor];
else
    self.backgroundColor = [UIColor greenColor];

}

like image 37
ChikabuZ Avatar answered Nov 12 '22 18:11

ChikabuZ