iosobjective-cswiftuilabelnstextattachment

Center NSTextAttachment image next to single line UILabel


I'd like to append an NSTextAttachment image to my attributed string and have it centered vertically.

I've used the following code to create my string:

NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:DDLocalizedString(@"title.upcomingHotspots") attributes:attrs];
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.image = [[UIImage imageNamed:@"help.png"] imageScaledToFitSize:CGSizeMake(14.f, 14.f)];
cell.textLabel.attributedText = [str copy];

However, the image appears to align to the top of the cell's textLabel.

text attachment offset problem screenshot

How can I change the rect in which the attachment is drawn?


Solution

  • You can change the rect by subclassing NSTextAttachment and overriding attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex:. Example:

    - (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex {
        CGRect bounds;
        bounds.origin = CGPointMake(0, -5);
        bounds.size = self.image.size;
        return bounds;
    }
    

    It's not a perfect solution. You have to figure out the Y-origin “by eye” and if you change the font or the icon size, you'll probably want to change the Y-origin. But I couldn't find a better way, except by putting the icon in a separate image view (which has its own disadvantages).