1

I have a UITableView populated with custom UITableViewCells. Within those custom cells, I have a UITextField and a "See More" UIButton. The purpose of the UIButton is to dynamically expand that particular UITableCell when the user wishes to read more of the text. In the same way, when the user wishes to return to the original size, the user clicks the Button again, and the UITableViewCell will shrink to the original size.

Since the cell isn't being selected, I setup an IBAction within the Custom Cell like such:

//Within CustomCell.m

- (IBAction)showMoreText:(id)sender
{
    //instance bool variable to flag whether the cell has been resized
    self.hasBeenResized = YES;

    //turn off mask to bounds, otherwise cell doesnt seem to resize
    [[self.cellView layer] setMasksToBounds:NO];

    // Calculate the new sizes and positions for the textView and the button 
    CGRect newTextViewFrame = self.textView.frame;
    newTextViewFrame.size.height = self.textView.contentSize.height;
    self.textView.frame = newTextViewFrame;

    CGFloat bottomYPos = self.textView.frame.origin.y + self.textView.frame.size.height;
    CGRect buttonFrame = self.showMoreButton.frame;
    buttonFrame.origin.y = bottomYPos;
    self.showMoreButton.frame = buttonFrame;

    // Call begin and end updates
    [(UITableView*) self.superview beginUpdates];   
    [(UITableView*) self.superview endUpdates];

    // Set mask and put rounded corners on the cell
    [[self.cellView layer] setMasksToBounds:YES];
    [[self.cellView layer] setCornerRadius:10.0];
}

Following this, I have this in my ViewController class:

// Within ViewController.m
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"heightForRowAtIndexPath");

    CustomCell *cell = (CustomCell*)[self tableView:tableView cellForRowAtIndexPath:indexPath];

    if([cell hasBeenResized] == NO)
    {
        return cell.frame.size.height + 20;
    }
    else
    {
        return cell.frame.size.height + cell.textView.frame.origin.y + cell.textView.frame.size.height + cell.showMoreButton.frame.size.height + 20;
    }
}

What happens now is I can see the custom cell change the size of its textview, however, the table does not update the row height for that particular cell. Checking on the If-else statement there, it appears that hasBeenResized is always false, even though I set it to YES within the IBACtion of the CustomCell.

I have looked at other solutions here, but they all seem to involve didSelectRowAtIndexPath, which I cannot use in this instance (I have another behavior for the cell when it is selected).

Am I doing this completely wrong? Ideally, what I would like to do is to have the "Show More" button animate downwards as the textview is expanded and vice versa when it's collapsed.

Thank you!

kurisukun
  • 3,149
  • 5
  • 37
  • 69

2 Answers2

3

Method beginUpdates won't call reloadData for you - you have to do it manually.

For your case it would be best to call:

- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation

And place your showMoreText code in tableView:cellForRowAtIndexPath: method (for selected cell only)

Rok Jarc
  • 18,765
  • 9
  • 69
  • 124
  • You could do it at the end of showMoreText (or in the method that calls showMoreText after this call) - you need indexPath of the cell where 'See More' button was clicked. – Rok Jarc Feb 24 '12 at 10:40
  • The same problem exists for me whether using this function or [table reloadData]. The row height animates, but the cell stays the same size. Removing the reloadData in my IBAction (which also contains the resizing CGRects), makes the cell resize, but not the row. – kurisukun Feb 24 '12 at 10:50
  • Hmm, your code for showMoreText should actually be implemented in cellForRowAtIndexPath (for the selected cell) - sorry for not noticing this before – Rok Jarc Feb 24 '12 at 10:52
  • Thank you for all the comments with regards to the question, I really appreciate it! With regards to putting the ShowMoreText within the cellForRowAtIndexPath, this would mean that I need to put some kind of flag or keep track of the rows that have the button tapped, right? – kurisukun Feb 24 '12 at 10:56
  • @kurisukun: yes. and then in cellForRowAtIndexPath you return all other cells 'normally' and the selected one with expanded content and frame. – Rok Jarc Feb 24 '12 at 11:05
0

To Update your tableView, you have to reload it.

[tableView reloadData];
Sree
  • 907
  • 5
  • 14
  • I put this within the IBAction of my CustomCell, but now the cell does not show any height changes. The row height did take effect however. – kurisukun Feb 24 '12 at 09:40
  • Ya.That's ok.But the TableView Datasource - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {return num; } will get called only on reload of the tableView – Sree Feb 24 '12 at 09:48
  • @kurisukun: nope, beginUpdates has nothing to do with calling heightForRowAtIndexPath. You'll need to call one of the reload methods. – Rok Jarc Feb 24 '12 at 10:42
  • I put an NSLog within heightForRowAtIndexPath, and called beginUpdates from my IBAction. The NSLog appeared when I tapped the button. Removing the beginUpdates from my IBAction also removed the NSLog output when tapping the Show More button. I figured this means this is getting called. – kurisukun Feb 24 '12 at 10:49