8

How can I go about getting my cells to redraw once the device is rotated?

When I am testing on iPhone, the default orientation is portrait, so my dynamic cells are as tall as they need to be when the device is in portrait orientation: this means when I rotate to landscape, there is a lot of empty space in the cell. When I test on iPad, it's the opposite. I get part of my text cut off when rotating to portrait orientation, as the default is landscape. I have separate storyboards for both devices, and both view controllers are set to "Orientation: Inferred"

enter image description here (Portrait) enter image description here (Landscape)

This is what's happening on iPhone - the stretching label has a dark red background so you can see the actual size of the label. However, the cell height is not recalculating and since the bottom labels are constrained to the bottom of the cell, they are all the way at the bottom by themselves. If I add a constraint from the stretching label (the one with the background) to the bottom of the cell, all it does is stretch the label like so:

enter image description here (Label is stretched)

What this tells me is that right now I'm just unable to get the cell to know what the orientation is and to redraw once it changes to fit. Here is my heightForRowAtIndexPath code that is calculating the height of the cell:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (!self.opCell)
        {
            self.opCell = [self.container dequeueReusableCellWithIdentifier:@"OPCell"];
        }
    self.opCell.opName.text = [[self.data objectAtIndex:indexPath.row] valueForKey:@"name"];
    [self.opCell layoutIfNeeded];
    CGFloat height = [self.opCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    return height + 1;
}

So far to get it to rotate I have tried [self.container reloadData], where container is my TableView with willRotateToInterfaceOrientation and didRotateToInterfaceOrientation to no avail. I also tried putting it in viewDidLoad, so as to maybe detect and load when the view is loaded in landscape mode with the correct height, but this didn't work either. For iPhone, no matter what I do it loads the height for portrait view and does not update on rotation.

I have found a few questions that I thought might help, but I can't seem to get this answer working for me, even though it seems like the same question I have, and this one seems to focus more on cell width than height and I'm not sure that it applies in the same way.

Here is even a tutorial that, when I ran it on the iPhone, is also not resizing the TableViewCells on rotation.

This tutorial seemed to have some insight into changing table heights, so I added the begin/endUpdates code into my didRotateToInterfaceOrientation, thinking that might cause a change, but this didn't work as well.

So, if anyone has any suggestions or knows a solution, it would be much appreciated, as I'm hitting a brick wall with this one!

Community
  • 1
  • 1
Eichhörnchen
  • 592
  • 2
  • 12
  • 27
  • You should move the stuff that has nothing to do with calculating the height out of the method... that'd be a good start. – nhgrif Jul 07 '14 at 22:20
  • 1
    I need all the code in my heightForRowAtIndexPath method. I have to declare the cell, declare the title I want to make dynamic height, then tell it to calculate the height with the last 2 lines. Dynamic cells are trickier than they need to be and this works. – Eichhörnchen Jul 07 '14 at 22:22
  • 1
    This is a nice tutorial how to create a dynamic tableViewCells. http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout – samir Jul 14 '14 at 21:09
  • @samir thanks! I followed one with a simpler method because I *thought* the tutorial on that site for dynamic cells was more pertaining to iOS6 or earlier. The example code on there seems to be doing what I need - consider adding this as an answer with some details/key points for the bounty.... – Eichhörnchen Jul 14 '14 at 23:00

3 Answers3

1

It seems you are doing a word wrap here. So as per my prior experience I suggest you to :
1) use sizeWithFont or the newer iOS7 version with appropriate linebreakmode.
2) You can implement layoutSubview for your "opCell" where you can redefine the frame size.
3) Calculate the cell height during the rotation.. ensure that you properly set the width as per the new tabelView Bounds.
4) Also you can implement estimatedHeightForRowAtIndexPath for quick estimated size for table reload operation.

Hope this helps !!

Vik
  • 21
  • 3
  • 1) I am currently resizing the label simply using a line count of 0 in storyboards, and it seems to be working. Should I use sizeWithFont in like, heightForRowAtIndexPath? will this only make a difference in the label height? and for 2 and 3 How do I implement cell size in these methods if I'm doing it there rather than heightForRowAtIndexPath? – Eichhörnchen Jul 14 '14 at 20:10
0

So I figured out my issue. Following this tutorial I found out that I was missing.

I had to:

  1. Subclass my label that was stretching and state that preferredMaxLayout is meeting the screen width

  2. In my heightForRowAtIndexPath I need to tell the cell to get and update the current width of the screen

See the tutorial for more details. Hope this question and answer helps someone along in the future, because this was extremely troublesome.

Eichhörnchen
  • 592
  • 2
  • 12
  • 27
-1

You could use the same trick as here. That is calling:

[tableView beginUpdates];
[tableView endUpdates];

Without anything in between. This will trigger heigh recalculation for the table view.

Community
  • 1
  • 1
Rivera
  • 10,792
  • 3
  • 58
  • 102
  • As I said, I tried this already and am not getting any results. I've tried to put this method in `ViewDidLoad`, `viewDidLayoutSubviews`, `heightForRowAtIndexPath`, `didRotateFromInterfaceOrientation` and `reloadRowsAtIndexPath`. Is there somewhere else I should put it? – Eichhörnchen Jul 10 '14 at 15:47
  • I would only set in in `didRotateFromInterfaceOrientation`. Most of the other methods you mention are triggered by `begin`/`endUpdates` and could result in a loop. – Rivera Jul 11 '14 at 03:03
  • i've tried it just there alone as well as with some other locations, this just isn't working for me. – Eichhörnchen Jul 14 '14 at 22:49