Anders
Anders

Reputation: 2941

Dynamically change UITextView height instead of scroll

I'm trying to create a simple Diary app. In it I have a ShowPostTableViewController where I want to display each post. In my tableView I have one section with two cells, one for the headline and one for the post's body. The headline is inside an UITextField and the body is inside a UITextView. I declare both like this:

UITextField * postHeadline;
UITextView * postText;

And i synthesize them in my implementation file. I setup the tableView's cells in the willDisplayCell method. It looks like this:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell   
forRowAtIndexPath:(NSIndexPath *)indexPath {

    tableView.allowsSelection = NO;

    CGRect wholeWindow = [self.view bounds];
    float headlineHeight = 40;

    CGRect headlineRect = CGRectMake(10, 10, wholeWindow.size.width, headlineHeight);

    CGRect bodyRect = CGRectMake(wholeWindow.origin.y, wholeWindow.origin.x, 
    wholeWindow.size.width, wholeWindow.size.height);

    postHeadline = [[UITextField alloc] initWithFrame:headlineRect];
    postText = [[UITextView alloc] initWithFrame:bodyRect];

    NSString * headline = [[NSString alloc] initWithFormat:@"%@",[currentPostArray 
    objectAtIndex:0]];

    NSString * body = [[NSString alloc] initWithFormat:@"%@",[currentPostArray 
    objectAtIndex:1]];

    postHeadline.text = headline;

    postHeadline.font = [UIFont fontWithName:@"Helvetica-Bold" size:24.0];

    postText.text = body;
    postText.backgroundColor = [UIColor colorWithRed:254.0/255.0 green:255.0/255.0   
        blue:237.0/255.0 alpha:1];
    postText.font = [UIFont fontWithName:@"Georgia" size:17.0];
    postText.scrollEnabled = NO;
    postText.delegate = self;

    if (indexPath.row == 0) {
        [cell.contentView addSubview:postHeadline];
    }
    if (indexPath.row == 1) {
        [cell.contentView addSubview:postText];
        CGRect frame = postText.frame;
        frame.size.height = postText.contentSize.height;
        postText.frame = frame;
    }
}

Yep, I'm a beginner, probably leaking memory like crazy. A question related to that. It seems like my UITextField postHeadline gets set twice, I can't erase it because it's two layers of the same text. How can I solve that?

Back to my original question. My cellForRowAtIndexPath is left petty much intact. I have sat up the delegate methods for my UITextView (think it's here the problem lies). I found a solution that almost worked here: UITextView change height instead of scroll.

They look like this:

- (void)textViewDidBeginEditing:(UITextView *)textView
{
    textView.frame =CGRectMake(textView.frame.origin.x,textView.frame.origin.y,textView.
frame.size.width,textView.frame.size.height + 100);

}

This method should resize the textView:

- (void)textViewDidChange:(UITextView *)textView
{

    CGFloat fontHeight = (textView.font.ascender - textView.font.descender) + 1;

    CGRect newTextFrame = textView.frame;
    newTextFrame.size = textView.contentSize;
    newTextFrame.size.height = newTextFrame.size.height + fontHeight;
    textView.frame = newTextFrame;

}

I set the row height like this:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath  
*)indexPath
{

    NSString * body = [[NSString alloc] initWithFormat:@"%@",[currentPostArray 
objectAtIndex:1]];

    CGSize bodySize = [body sizeWithFont:[UIFont fontWithName:@"Georgia" size:17.0] 
constrainedToSize:CGSizeMake(self.view.frame.size.width,CGFLOAT_MAX)];

    if (indexPath.section == 0 && indexPath.row == 1) {
        return bodySize.height + 100;
    }    
    return 50;
}

The thing almost works. When the user hits return, the textview seems to expand, but it only works 14 times, then the cursor hides behind the keyboard.

Any ideas and tips how to solve this would be great!

Thanks // Anders

EDIT

I solved the "headline gets set twice" problem by moving most of my willDisplayCell method code to my viewDidLoad method. And I think I have localized where the rezising problem is. I think it is in my heightForRowAtIndexPath method. It currently looks like this:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath    
*)indexPath
{

    NSString * body = [[NSString alloc] initWithFormat:@"%@",[currentPostArray   
objectAtIndex:1]];

    CGSize bodySize = [body sizeWithFont:[UIFont fontWithName:@"Georgia" size:17.0]  
constrainedToSize:CGSizeMake(self.view.frame.size.width,CGFLOAT_MAX)];

    if (indexPath.section == 0 && indexPath.row == 1) {
        return bodySize.height + 100;
    }    
    return 50;
}

Since array and it's content gets set in the viewDidLoad method, the size stays the same. I therefore think I need to dynamically increase the cell's size after my TextView's content too. Because when I write like this:

if (indexPath.section == 0 && indexPath.row == 1) {
    return 1000;
}   

The cell's size increases and the user can hit "return" more times before the keyboard gets in the the way. Is there a way to increase to cells's height dynamically?

Upvotes: 0

Views: 4216

Answers (1)

Anders
Anders

Reputation: 2941

Think I solved it. These methods did the magic trick:

[self.tableView beginUpdates];
[self.tableView endUpdates];

I updated my heightForRowAtIndexPath so it looks like this:

if (indexPath.section == 0 && indexPath.row == 1) {        
    return postText.frame.size.height + headlineHeight; 
}    
return 44;

And I added these methods to viewDidChange and in viewWillAppear (to reset the sizes).

[self.tableView beginUpdates];
[self.tableView endUpdates];

That was pretty much it.

Upvotes: 1

Related Questions