Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
NSTextAttachment that scales and aligns image
// Created by Tony Mann on 3/22/15.
// Copyright (c) 2015 7Actions. All rights reserved.
//
// Adapted from http://ossh.com.au/design-and-technology/software-development/implementing-rich-text-with-images-on-os-x-and-ios/
import UIKit
class ImageAttachment: NSTextAttachment {
var verticalOffset: CGFloat = 0.0
// To vertically center the image, pass in the font descender as the vertical offset.
// We cannot get this info from the text container since it is sometimes nil when `attachmentBoundsForTextContainer`
// is called.
convenience init(_ image: UIImage, verticalOffset: CGFloat = 0.0) {
self.init()
self.image = image
self.verticalOffset = verticalOffset
}
override func attachmentBoundsForTextContainer(textContainer: NSTextContainer, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect {
let height = lineFrag.size.height
var scale: CGFloat = 1.0;
let imageSize = image!.size
if (height < imageSize.height) {
scale = height / imageSize.height
}
return CGRect(x: 0, y: verticalOffset, width: imageSize.width * scale, height: imageSize.height * scale)
}
}
@llinardos
Copy link

llinardos commented Oct 11, 2017

If you're working on an objc project:

@interface ImageAttachment : NSTextAttachment

@property (nonatomic, assign) CGFloat verticalOffset;

- (instancetype)initWithImage:(UIImage *)image verticalOffset:(CGFloat)offset;

@end

@implementation ImageAttachment

- (instancetype)initWithImage:(UIImage *)image verticalOffset:(CGFloat)offset {
    self = [super init];
    if (self) {
        self.image = image;
        self.verticalOffset = offset;
    }
    return self;
}

- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex {
    CGFloat height = lineFrag.size.height;
    CGFloat scale = 1.0;
    CGSize imageSize = self.image.size;
    
    if (height < imageSize.height) {
        scale = height / imageSize.height;
    }
    
    return CGRectMake(0, _verticalOffset, imageSize.width * scale, imageSize.height * scale);
}

@end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment