Search code examples
objective-cuitextviewnsattributedstringnstextattachment

How to convert uitextview content to a image in custom size?


I create a uitextview and I can add text and images to it with NSAttributedString and NSTextAttachment

  self.tvContent = [[UITextView alloc] initWithFrame:CGRectMake(0, 20, 
  self.view.frame.size.width, self.view.frame.size.height - 64)];
  self.tvContent.font = [UIFont fontWithName:@"Arial" size:16.0f];
  self.tvContent.backgroundColor = [UIColor whiteColor];
  self.tvContent.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);
  self.tvContent.contentInset = UIEdgeInsetsMake(0, 0, 10, 0);
  self.tvContent.layoutManager.allowsNonContiguousLayout=NO;
  [self.view addSubview:self.tvContent];

And I convert its content to image with following code

  - (UIImage *)imageFromView:(UITextView *)view {
    CGRect tmpFrame = self.view.frame;
    CGRect aFrame = view.frame;
    aFrame.size.height  = [view sizeThatFits:[[UIScreen mainScreen] bounds].size].height;
    view.frame = aFrame;
    UIGraphicsBeginImageContext([view sizeThatFits:[[UIScreen mainScreen] bounds].size]);
    CGContextRef resizedContext = UIGraphicsGetCurrentContext();
    [view.layer renderInContext:resizedContext];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    view.frame = tmpFrame;
    return image;
 }

This image's max-width is 375(iPhone 6), if I wrote less content, such as 1234, the image's width is 40, so how can I convert the content to image with custom size, such as the width is 750, and the height is as long as the content height? Any ideas? many thanks.


Solution

  • The UITextView only renders within it's current frame, so you need to either resize the frame to the desired size before rendering, or create a temporary UITextView object to use for rendering purpose.

    Here is how rendering with a temporary object can be done:

    // Your call to get the image
        UIImage *image = [self imageFromTextView:self.tvContent width:750.0]; // Any width you want
    
    // Your text view properties that also can be used for rendering purpose
    - (void)setupTextViewProperties:(UITextView *)textView {
        textView.font = [UIFont fontWithName:@"Arial" size:16.0f];
        textView.backgroundColor = [UIColor whiteColor];
        textView.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);
        textView.contentInset = UIEdgeInsetsMake(0, 0, 10, 0);
        textView.layoutManager.allowsNonContiguousLayout=NO;
    }
    

    Set up of the temporary UITextView object used for rendering.

    - (UIImage *)imageFromTextView:(UITextView *)view width:(CGFloat)desiredWidth {
        // Create a new temporary UITextView to use for rendering
        CGRect frame = CGRectMake(0.0, 0.0, desiredWidth, 0.0);
        UITextView *temporaryTextView = [[UITextView alloc] initWithFrame:frame];
    
        // Setup the temporary text view
        // You can have different font, colors etc from the original view
        [self setupTextViewProperties:temporaryTextView];
        temporaryTextView.attributedText = view.attributedText;
    
        // Calculate the height needed for content with width
        CGSize size = CGSizeMake(desiredWidth, 0.0);
        size = [temporaryTextView sizeThatFits:size];
    
        // Resize the temporary view
        // Note that the calculated size can contain a width smaller that desired with
        temporaryTextView.frame = CGRectMake(0.0, 0.0, desiredWidth, size.height);
    
        // Get the image
        return [self imageFromView:temporaryTextView];
    }
    

    Helper that can render any view as an image.

    - (UIImage *)imageFromView:(UIView *)view {
        CGSize size = view.bounds.size;
        UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
        CGContextRef context = UIGraphicsGetCurrentContext();
        [view.layer renderInContext:context];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return image;
    }