Damian Dudycz
Damian Dudycz

Reputation: 2810

Autoresizing Image in NSAttributedString with UITextView

Im trying to make UITextView display rtfd document with image in it. The problem is, that the image is overlapping the frame of UITextView - it has larger width. I need this image to scale to width of UITextView. This is how I load the string:

if let text = try? NSMutableAttributedString(URL: NSBundle.mainBundle().URLForResource("License agreement", withExtension: "rtfd")!, options: [NSDocumentTypeDocumentAttribute : NSRTFDTextDocumentType], documentAttributes: nil) {

        textView.attributedText = text
    }

I also tried with webarchive file with img style="width: 100%", but this also didn't work.

What is the best way to display rtfd or other document in such a way, so that images are scaled to fit the width?

Upvotes: 4

Views: 2875

Answers (2)

guozqzzu
guozqzzu

Reputation: 899

If you po the textView's attributeText property you can found it has many objects like this:

NSAttachment = "<NSTextAttachment: 0x6000002a39c0> \"XXXXXXX.jpg\"";
NSColor = "kCGColorSpaceModelRGB 0 0 0 1 ";
NSFont = "<UICTFont: 0x7f8356400f60> font-family: \"Times New Roman\"; font-weight: normal; font-style: normal; font-size: 12.00pt";
NSKern = 0;
NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 12, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 15/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n), DefaultTabInterval 36, Blocks (\n), Lists (\n), BaseWritingDirection 0, HyphenationFactor 0, TighteningForTruncation NO, HeaderLevel 0";
NSStrokeColor = "kCGColorSpaceModelRGB 0 0 0 1 ";
NSStrokeWidth = 0;  

Then you will find that the NSTextAttachment is the Bingo. So enum those objects, get the NSTextAttachment and change the bounds of it : (I set the image has a 10px margin to right screen)

[attributeString enumerateAttribute:NSAttachmentAttributeName inRange:NSMakeRange(0, attributeString.length) options:0 usingBlock:^(id  _Nullable value, NSRange range, BOOL * _Nonnull stop) {

            if (value) {

                if ([value isKindOfClass:[NSTextAttachment class]]) {

                    NSTextAttachment *attach = value;
                    CGFloat scale  = SCREEN_WIDTH / attach.bounds.size.width;
                    CGRect newRect = CGRectMake(attach.bounds.origin.x, attach.bounds.origin.y,SCREEN_WIDTH-10, attach.bounds.size.height*scale);
                    attach.bounds  = newRect;
                }
            }
        }];

Upvotes: 0

Damian Dudycz
Damian Dudycz

Reputation: 2810

Thank you Larme for you comment, I managed to make it work like this:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    prepareTextImages()
}

private var text: NSMutableAttributedString?
private func prepareTextImages() {
    let width  = CGRectGetWidth(self.view.frame) - self.containerView.frame.origin.x * 2 - 10
    text?.enumerateAttribute(NSAttachmentAttributeName, inRange: NSRange(location: 0, length: text!.length), options: [], usingBlock: { [width] (object, range, pointer) in
        let textViewAsAny: Any = self.textView
        if let attachment = object as? NSTextAttachment, let img = attachment.imageForBounds(self.textView.bounds, textContainer: textViewAsAny as? NSTextContainer, characterIndex: range.location) {
            if attachment.fileType == "public.png" {
                let aspect = img.size.width / img.size.height
                if img.size.width <= width {
                    attachment.bounds = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)
                    return
                }
                let height = width / aspect
                attachment.bounds = CGRect(x: 0, y: 0, width: width, height: height)
            }
        }
        })
}

There is small problem with this - when scrolling I see a small lag when viewing this image. Doesn't happened with full size image without changing its size. Can someone think of a reason for this?

Upvotes: 3

Related Questions