Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITextView wraps text when built with iOS 7 SDK

I have a UITextView inside a UIScrollView that worked perfectly fine on iOS 6 built from xcode 4.x, however now building with xcode 5 it doesn't work properly, even on iOS 6.

The problem is the text wraps with the screen width even though the UITextView and UIScrollView have large widths. I use this code to work out the new width and height of the UITextView, and even though the textview scrolls left/right the text is wrapped as if the width is only the width of the screen.

Thanks

self.responceTextView.text = [NSString stringWithFormat:@"%@%@",_responceTextView.text,responce];
[self textViewDidChange:self.responceTextView];

- (void)textViewDidChange:(UITextView *)textView
{
    // Recalculate size of text field
    CGSize maxSize = CGSizeMake(MAXFLOAT, MAXFLOAT);
    CGSize reqSize = [textView.text sizeWithFont:[UIFont fontWithName:@"Courier" size:12] constrainedToSize:maxSize lineBreakMode:NSLineBreakByClipping];

    self.responceTextView.frame = CGRectMake(0, 0, reqSize.width+16, reqSize.height+16);

    // Resize scroll view if needs to be smaller so text stays at top of screen
    CGFloat maxScrollHeight = maxScrollViewSize.size.height;
    if (self.responceTextView.frame.size.height < maxScrollHeight) {
        self.responceScrollView.frame = CGRectMake(self.responceScrollView.frame.origin.x, self.responceScrollView.frame.origin.y, self.responceScrollView.frame.size.width, self.responceTextView.frame.size.height);
    } else {
        self.responceScrollView.frame = maxScrollViewSize;
    }

    // Set content size
    self.responceScrollView.contentSize = CGSizeMake(self.responceTextView.frame.size.width, self.responceTextView.frame.size.height);

    [self scrollToCursor];
}

EDIT ----

Ok, so it seems sizeWithFont is deprecated in iOS 7. Strange how I get no compiler warning. It still doesn't make sense that it doesn't work on iOS 6 (or is it completely removed when built with iOS 7 SDK?)

I have tried these 2 alternatives, but get exactly the same size back from all.

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                [UIFont fontWithName:@"Courier" size:12], NSFontAttributeName,
                                nil];
CGRect rect = [textView.text boundingRectWithSize:maxSize options:NSLineBreakByClipping | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil];

returns: {{0, 0}, {439.27148, 168}}

CGSize rect2 = [textView.text sizeWithAttributes:attributes];

returns: {439.27148, 168}

And the original above returns {439.27148, 168}

They should all return a wider view.

EDIT 2 ---- It seems from above that the returned frame is correct (439 wide) however it's the text that is still being word wrapped inside the textview.

like image 456
Darren Avatar asked Sep 18 '13 08:09

Darren


2 Answers

try using:

[textView.text boundingRectWithSize:CGSizeMake(txtFrame.size.width, CGFLOAT_MAX)
                           options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                           attributes:[NSDictionary dictionaryWithObjectsAndKeys:textView.font,NSFontAttributeName, nil] context:nil];

The string measuring seems pretty buggy. This is the only option combination that gives the right size, for the testing I have done.

I'm using the following code with success in iOS7 (it's a UITextField with a minimum and maximum height. When the text's height get larger then MAX_HEIGHT_MESSAGE_TEXTBOX, scrollbars appears in the UITextField).

const float MAX_HEIGHT_MESSAGE_TEXTBOX = 80;
const float MIN_HEIGHT_MESSAGE_TEXTBOX = 30;


- (void)setFrameToTextSize:(CGRect)txtFrame textView:(UITextView *)textView
{

    if(txtFrame.size.height > MAX_HEIGHT_MESSAGE_TEXTBOX)
    {
        //OK, the new frame is to large. Let's use scroll
        txtFrame.size.height = MAX_HEIGHT_MESSAGE_TEXTBOX;
        textView.scrollEnabled = YES;
        [textView scrollRangeToVisible:NSMakeRange([textView.text length], 0)];
    }
    else
    {
        if (textView.frame.size.height < MIN_HEIGHT_MESSAGE_TEXTBOX) {
             //OK, the new frame is to small. Let's set minimum size
            txtFrame.size.height = MIN_HEIGHT_MESSAGE_TEXTBOX;
        }
        //no need for scroll
        textView.scrollEnabled = NO;
    }
    //set the frame
    textView.frame = txtFrame;
}

- (void)setframeToTextSize:(UITextView *)textView animated:(BOOL)animated
{
    //get current height
    CGRect txtFrame = textView.frame;

    //calculate height needed with selected font. Note the options.
    //append a new line to make space for the cursor after user hit the return key
    txtFrame.size.height =[[NSString stringWithFormat:@"%@\n ",textView.text]
                           boundingRectWithSize:CGSizeMake(txtFrame.size.width, CGFLOAT_MAX)
                           options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                           attributes:[NSDictionary dictionaryWithObjectsAndKeys:textView.font,NSFontAttributeName, nil] context:nil].size.height;

    if (animated) {
        //set the new frame, animated for a more nice transition
        [UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseOut |UIViewAnimationOptionAllowAnimatedContent animations:^{
            [self setFrameToTextSize:txtFrame textView:textView];
        } completion:nil];
    }
    else
    {
        [self setFrameToTextSize:txtFrame textView:textView];
    }
}

- (void)textViewDidChange:(UITextView *)textView
{
    [self setframeToTextSize:textView animated:YES];
}

EDIT

When the string measuring is correct, you might need to change the lineBreakModeon the UITextView's textContainer. (NSTextContainer is a new class in iOS7, containing information about how text should be laid out):

textView.textContainer.lineBreakMode = NSLineBreakByCharWrapping; // default is NSLineBreakByWordWrapping 

Good luck!

like image 91
EsbenB Avatar answered Nov 10 '22 02:11

EsbenB


method sizeWithFont:(UIFont *)font constrainedToSize ..." has been deprecated in iOS 7.

It would function properly.

Check out its alternate in iOS 7

Instance Method of NSString

-(CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:

(NSDictionary *)attributes context:(NSStringDrawingContext *)context

Check this answer out. Replacement for deprecated sizeWithFont: in iOS 7?

like image 36
Muhammad Idris Avatar answered Nov 10 '22 01:11

Muhammad Idris