Search code examples
iosuitextviewios7

iOS7 UITextView contentsize.height alternative


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.


Solution

  • 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:)])‌