iOS7 UITextView contentsize.height alternative

65,308

Solution 1

With this following code, you can change the height of your UITextView depending of a fixed width (it's working on iOS 7 and previous version) :

- (CGFloat)textViewHeightForAttributedText:(NSAttributedString *)text andWidth:(CGFloat)width
{
    UITextView *textView = [[UITextView alloc] init];
    [textView setAttributedText:text];
    CGSize size = [textView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

With this function, you will take a NSAttributedString and a fixed width to return the height needed.

If you want to calculate the frame from a text with a specific font you, need to use the following code :

- (CGSize)text:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
    {
        CGRect frame = [text boundingRectWithSize:size
                                          options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                       attributes:@{NSFontAttributeName:font}
                                          context:nil];
        return frame.size;
    }
    else
    {
        return [text sizeWithFont:font constrainedToSize:size];
    }
}

You can add that SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO on your prefix.pch file in your project as:

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

You can also replace the previous test SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) by :

if ([text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])‌

Solution 2

This worked for me for iOS6 and 7:

CGSize textViewSize = [self.myTextView sizeThatFits:CGSizeMake(self.myTextView.frame.size.width, FLT_MAX)];
    self.myTextView.height = textViewSize.height;

Solution 3

In iOS7, UITextView uses NSLayoutManager to layout text:

// If YES, then the layout manager may perform glyph generation and layout for a given portion of the text, without having glyphs or layout for preceding portions.  The default is NO.  Turning this setting on will significantly alter which portions of the text will have glyph generation or layout performed when a given generation-causing method is invoked.  It also gives significant performance benefits, especially for large documents.
@property(NS_NONATOMIC_IOSONLY) BOOL allowsNonContiguousLayout;

disable allowsNonContiguousLayout to fix contentSize :

textView.layoutManager.allowsNonContiguousLayout = NO;

Solution 4

Use this little function

-(CGSize) getContentSize:(UITextView*) myTextView{
    return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}

Solution 5

My final solution is based on HotJard's but includes both top and bottom insets of text container instead of using 2*fabs(textView.contentInset.top) :

- (CGFloat)textViewHeight:(UITextView *)textView
{
    return ceilf([textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height +
                 textView.textContainerInset.top +
                 textView.textContainerInset.bottom);
}
Share:
65,308

Related videos on Youtube

Zoltan Varadi
Author by

Zoltan Varadi

Updated on July 05, 2022

Comments

  • Zoltan Varadi
    Zoltan Varadi almost 2 years

    I'm porting one of apps from iOS 6.1 to iOS 7. I'm using a layout where there's a UITextView that has a fix width, but it's height is based on its contentsize. For iOS 6.1 checking the contentsize.height and setting it as the textview's frame height was enough, but it doesn't work on iOS 7.

    How can I then create a UITextView with a fixed width, but dynamic height based on the text it's showing?

    NOTE: I'm creating these views from code, not with Interface Builder.

  • Zoltan Varadi
    Zoltan Varadi over 10 years
    i can only give it to you after 24 hours. be patient, it's yours :)
  • andrew-caulfield
    andrew-caulfield over 10 years
    Maybe you should link to the answers you took them from? stackoverflow.com/questions/18368567/…
  • Valerii  Pavlov
    Valerii Pavlov over 10 years
    It seems like your solition doesnt work. When textview goto second line usedRectForTextContainer method returns same height.
  • HotJard
    HotJard over 10 years
    Oh, may be, I'v just use it for displaying text
  • LiangWang
    LiangWang over 10 years
    @Jordan Montel, for another question, if i have fixed width and height , how can i find the best font size for an assigned string? i have the similar issue on iOS7 (on iOS6, i can do that)
  • Cœur
    Cœur over 10 years
    @Jacky : trial and error; increase or decrease the size by 1 until its calculated height is too big. Or make it size 1000 and auto-resize to fit.
  • Mani
    Mani over 10 years
    Hi, Yes its woking for me… I am used "txtviewHeight.frame.size.height" instead of "txtviewHeight.contentSize.height"
  • Paul Brady
    Paul Brady over 10 years
    Works in iOS6 and iOS7 for me. Thanks!
  • vietstone
    vietstone about 10 years
    Your answer is not fit the question, but fit my problem. So I vote up :)
  • Hexark
    Hexark almost 10 years
    why am i getting property height not found on object of type "UITextView" ?
  • user
    user almost 10 years
    @Hexark textView.bounds.size.height
  • user2159978
    user2159978 over 9 years
    this answer is ALREADY INCORRECT. Try to input a lot of text inside such text field. Suddenly incorrect size? At least NSStringDrawingUsesFontLeading is extra
  • samthui7
    samthui7 about 8 years
    (NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) helps me a lot.
  • Dvole
    Dvole almost 8 years
    This does not fix content size for me. Scrolling is disabled.
  • Code Farmer
    Code Farmer almost 8 years
    This piece of code solved my problem, but what does generation-causing method mean on you comment?