8

I have a UITextView that I need to resize so that it has a width that stretches to fill the screen but variable height so that it is just big enough to show all the text. When the resizing takes place it should make the UITextView the minimum possible height so that it fits the in.

In order to do this I have been using the following code:

textView.text            = textMessage;
[textView sizeToFit];
CGRect rect              = textView.frame;
rect.size.height         = textView.contentSize.height;
textView.frame           = rect;

When I do this it doesn't seem to make the UITextView the minimum height possible. It appears that there is some excess space left below. Here is an example (I have set the background colour to red in order to illustrate my point):

enter image description here

Please could someone advise why this is happening and how I can resolve the issue? Please note that the UITextView is located within a custom UITableView cell. This cell uses the Autoresizing masks to stretch horizontally to fill the screen depending on the orientation.

I have spend ages trying to get this to work but I don't see why there is excess space at the bottom and also when I rotate the device the height of the UITextViews all seem to remain the same (even though I call the [UITableView reloadData] method which I have also defined the row heigh method for).

  • You could try myTextView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f); – Rachel Gallen Jan 27 '13 at 11:35
  • No I have no padding. I have also tried the UIEdgeInsetsMake solution, however it didn't change the appearance at all. –  Jan 27 '13 at 21:04
  • I don't think `contentSize` will get you the size of the formatted content. It is more like with scroll views where you specify the content size you can scroll around. At least thats what I thought about it, maybe I'm wrong. `NSLog` the size and see if its changing for different text. Otherwise if it is always one line larger than the actual text you can simply subtract a fixed value like 12pt. –  Feb 02 '13 at 00:07
  • if your are not editing text inside the text view then use UILabel it'll work well. – rptwsthi Feb 08 '13 at 10:46

5 Answers5

9

I had the same problem once and found this.

CGSize maximumLabelSize = CGSizeMake(300,80);//Or whatever size you need to be the max

CGSize expectedLabelSize = [textMessage sizeWithFont:[UIFont boldSystemFontOfSize:18] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeWordWrap];
rect.size.height = expectedLabelSize.height;
textView.frame = rect;

Hope this helps.

mpwhitt
  • 485
  • 1
  • 5
  • 14
  • yes … with the implication that you fill in the font with whatever you're interested in to replace `[UIFont boldSystemFontOfSize:18]` . – john.k.doe Feb 02 '13 at 01:37
  • This should work, but it should be placed in a location that will be called whenever the view is resized. `layoutSubviews` of a parent view might be a good place to stick this. – Kekoa Feb 07 '13 at 06:56
2

Here is the solution to your problem.

//
//  CustomCell.m
//  Custom
//
//  Created by Syed Arsalan Pervez on 2/8/13.
//  Copyright (c) 2013 SAPLogix. All rights reserved.
//

#import "CustomCell.h"

@implementation CustomCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
        _textView = [[UITextView alloc] initWithFrame:CGRectZero];
        [_textView setBackgroundColor:[UIColor clearColor]];
        [_textView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
        [[self contentView] addSubview:_textView];
    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    [_textView setFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}

- (void)dealloc
{
    [_textView release];
    [super dealloc];
}

@end

Using the cell.

//
//  TestViewController.m
//  Custom
//
//  Created by Syed Arsalan Pervez on 2/8/13.
//  Copyright (c) 2013 SAPLogix. All rights reserved.
//

#import "TestViewController.h"
#import "CustomCell.h"

@interface TestViewController ()

@end

@implementation TestViewController

- (void)viewDidLoad
{
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2;
}

#define DEFAULT_TEXT @"This is an example block of text which seems to run over the edge of the UITableView so it no longer shows up the way I want."

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *_identifier = @"CustomCell";
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:_identifier];
    if (!cell)
    {
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:_identifier];
        [[cell contentView] setBackgroundColor:[UIColor redColor]];
    }

    cell.textView.text = DEFAULT_TEXT;

    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGRect frame = [[UIApplication sharedApplication] statusBarFrame];
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
// You can replace DEFAULT_TEXT with text you want to be displayed in the cell.
    CGSize size = [DEFAULT_TEXT sizeWithFont:[UIFont systemFontOfSize:13] constrainedToSize:CGSizeMake( UIInterfaceOrientationIsPortrait(orientation) ? frame.size.width : frame.size.height, 9999)];

    return size.height;
}

- (UIInterfaceOrientation)interfaceOrientation
{
    return (UIInterfaceOrientation)UIInterfaceOrientationMaskAll;
}

- (void)dealloc
{
    [super dealloc];
}

@end
SAPLogix
  • 1,744
  • 1
  • 11
  • 9
1

The superview of the UITextView (or a sibling view is the bottom edge of your UITextView is pinned to) is what is keeping the height of the UITextView from decreasing. Without knowing the view hierarchy of your view, I would suggest calling setNeedsLayout on the parent view of the UITextView.

Fruity Geek
  • 7,351
  • 1
  • 32
  • 41
1

I too had the same problem in two of my past projects. What i did was this.

- (float)getHeightFortheDynamicLabel:(NSString *)stringForTheLabel
{
    CGSize maxSize = CGSizeMake(215, 2000.0);
    CGSize newSize = [stringForTheLabel sizeWithFont:[UIFont systemFontOfSize:14.0]
                                   constrainedToSize:maxSize];
    return newSize.height;
}

Just pass the string whose height you need to determine, and this method will return you the size. Set this height for your label.

Also note that instead of UITextView, use a UILabel with number of lines set to 0. This method works just perfect with Label. In the beginning I too used UITextView which caused the an offset problem. Later with label this worked perfect. Try with a UILabel. Hope this helps you. And also double check the size of font you used for the label. Make them same (for label and value given inside the method).

Meera
  • 1,031
  • 6
  • 25
0

I agree with mpwhitt, but would add a slight difference to take into effect the stretching nature of your table cells.

    CGSize expectedLabelSize = [textView.text sizeWithFont:textView.font 
           constrainedToSize:CGSizeMake(textView.frame.size.width,9999)
           lineBreakMode:UILineBreakModeWordWrap];

    rect.size.height = expectedLabelSize.height;
    textView.frame = rect;

That way you don't have to worry if the font changes or if the label width changes. I'm uncertain if this will remove that small strip of excess height, but I've never needed this to work as exactly as you are asking.

Would it be possible to just subtract 3-5 pixels from the height you find?

Putz1103
  • 6,211
  • 1
  • 18
  • 25