2

I have created Custom UITableViewCell using XIB file and got it working in UITableView. I have designed custom cell and it's subviews in portrait sizes but when I rotate device in landscap mode I want to resize cell and it's subviews. I have written following code for this but not sure why only one cell in visible cells get resized and rest stays same! Could someone please help me with the standard practice to resize custom cell and their subviews? Thanks.

#pragma mark - UITableView delegate methods

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"CustomTableViewCellIdentifier";
    CustomTableViewCell *cell = (CustomTableViewCell*)[tv dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        // Load custom cell from NIB
        self.customTableViewCell = [[[NSBundle mainBundle] loadNibNamed:@"CustomTableViewCell" owner:self options:nil] objectAtIndex:0];
        cell = _customTableViewCell;
    }
    // Use cell
    ...
}

#pragma mark - Layout views

- (void)layoutForOrientation:(UIInterfaceOrientation)orientation {
    if (UIInterfaceOrientationIsPortrait(orientation))
        [self layoutPortraitViews];
    else
        [self layoutLandscapViews];
}

- (void)layoutLandscapViews {
    self.customTableViewCell.frame = CGRectMake(0, 0, 1024, 40);
    self.customTableViewCell.contentSize = CGSizeMake(1024, 40);
    self.customTableViewCell.cellBackgroundImageView.frame = CGRectMake(0, 0, 1024, 40);
    self.customTableViewCell.assetNameLabel.frame = CGRectMake(15, 0, 245, 20);
    self.customTableViewCell.assetTypeLabel.frame = CGRectMake(15, 20, 245, 20);
    self.customTableViewCell.assetImageView.frame = CGRectMake(265, 20, 120, 20);
    self.customTableViewCell.assetValueLabel.frame = CGRectMake(265, 20, 120, 20);

    [self.tableView reloadData];
}

- (void)layoutPortraitViews {
    self.customTableViewCell.frame = CGRectMake(0, 0, 768, 40);
    self.customTableViewCell.contentSize = CGSizeMake(768, 40);
    self.customTableViewCell.cellBackgroundImageView.frame = CGRectMake(0, 0, 768, 40);
    self.customTableViewCell.assetNameLabel.frame = CGRectMake(15, 0, 180, 20);
    self.customTableViewCell.assetTypeLabel.frame = CGRectMake(15, 20, 180, 20);
    self.customTableViewCell.assetImageView.frame = CGRectMake(200, 20, 90, 20);
    self.customTableViewCell.assetValueLabel.frame = CGRectMake(200, 20, 90, 20);

    [self.tableView reloadData];
}

[SOLUTION]

After little struggle got this working. Changing the size of cell and it's subviews not going to work as I have to handle orientation changes, keep reusing cell for performance, and visible cells changes when you rotate the device so couldn't figure out the solution using my first approach. Here is my another solution.

Here challenge is to handle orientations and custom cells together without compromising performance.

I have created two cell views in NIB, one for portrait and another for landscap.

Used two variables;

BOOL refreshing;
UIInterfaceOrientation currentOrientation;

From view will appear;

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    currentOrientation = [UIApplication sharedApplication].statusBarOrientation;
    [self layoutForOrientation:[UIApplication sharedApplication].statusBarOrientation];
}

From rotation delegates;

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    refreshing = YES;
    currentOrientation = toInterfaceOrientation;
    [UIView animateWithDuration:duration animations:^{
        [self.tableView reloadData];
        [self layoutForOrientation:toInterfaceOrientation];
    }];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    refreshing = NO;
}

From tableview delegate;

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"CustomTableViewCellIdentifier";
    CustomTableViewCell *cell = (CustomTableViewCell*)[tv dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil || refreshing)
     {
        if (UIInterfaceOrientationIsPortrait(currentOrientation))
            cell = [[[NSBundle mainBundle] loadNibNamed:@"CustomTableViewCell" owner:self options:nil] objectAtIndex:0];
         else 
            cell = [[[NSBundle mainBundle] loadNibNamed:@"CustomTableViewCell" owner:self options:nil] objectAtIndex:1];
    }

    //Use cell
}

...so this solution will reload cells only when orientation changed event happens. Happy coding :-)

Paresh Masani
  • 7,474
  • 12
  • 73
  • 139

3 Answers3

0

Resizing a custom NIB xib cell may or may not provide the desirec UI on rotation.To make the task easier..create two UITableViewCell nibs

 if (!cell) {
            if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) {
                [[NSBundle mainBundle] loadNibNamed:@"CustomTableViewCell-Landscape" owner:self options:nil];
            }else {
                [[NSBundle mainBundle] loadNibNamed:@"CustomTableViewCell" owner:self options:nil];
     }
}

Further call [tableView reloadData]; on orientation change

AppleDelegate
  • 4,269
  • 1
  • 20
  • 27
  • I thought this but there must be a way to make my code working. I think what's happening is after cell nib loaded tabview keep using the same even after I modified sizes programatically. If I assign self. customTableViewCell directly to cell without dequeueing then I just have one cell in uitableview with strange blinking between other cells....so annoying! – Paresh Masani Nov 02 '12 at 12:03
  • BTW reloadingData doesn't reload cells, just data changes not GUIs! – Paresh Masani Nov 02 '12 at 13:33
  • Accepting your answer as this was the nearest to what I did. Thanks. :-) – Paresh Masani Nov 02 '12 at 15:03
0

Because you self.customTableViewCell instant overwrite all time. so its return last object only.

you should write below code to resize your all UITableViewCells

for(UITableViewCell *cell in self.tableView.visibleCells)
{
     if([cell isKindOfClass:[UITableViewCell class]])
     {
          cell.frame = CGRectMake(0, 0, 1024, 40);
          cell.contentSize = CGSizeMake(1024, 40);
          cell.cellBackgroundImageView.frame = CGRectMake(0, 0, 1024, 40);
          cell.assetNameLabel.frame = CGRectMake(15, 0, 245, 20);
          cell.assetTypeLabel.frame = CGRectMake(15, 20, 245, 20);
          cell.assetImageView.frame = CGRectMake(265, 20, 120, 20);
          cell.assetValueLabel.frame = CGRectMake(265, 20, 120, 20);
     }
}
Romit M.
  • 898
  • 11
  • 28
  • I hope it's that simple! I am changing self.customTableViewCell properties on orientation change which is perfectly right but UITableView is not using modified properties of cell, that's a problem. If I ask tabview to use modified cell forcefully in cellForRowAtIndexPath - "cell = _customTableViewCell;" (without checkin cell==nil) then it's creating strange issues! – Paresh Masani Nov 02 '12 at 12:05
  • you don't need to create property for customTableViewCell. create cell object locally, which is much better to implement. is you will not check (cell==nil) them you application might be crash after some time. – Romit M. Nov 02 '12 at 12:08
  • Hmm that makes sense! I made these changes but it's not working! There must be something to do with already loaded NIB cell! I have to unload it and forcefully use modified cell. – Paresh Masani Nov 02 '12 at 12:25
  • Hi Romit, this seems to be working but it is not resizing all cells! I would say it's resizing about half the cells only! Any ideas why that happens? – Paresh Masani Nov 02 '12 at 13:50
0

I think this can be accomplished by the correct use of the autoresizing masks inside interface builder (or the new Auto Layout), instead of resizing the frame by code each time.

quarac
  • 3,454
  • 3
  • 21
  • 25
  • It can't be! You can use auto layout and auto resizing only when you don't want fixed size and position of controls but I am very particular about those values. – Paresh Masani Nov 02 '12 at 12:07
  • Ok men, what about overwriting layoutSubviews inside your CustomTableViewCell class? – quarac Nov 02 '12 at 12:10