I've got an attributed string with an image attached (NSTextAttachment
). This works alright, but I've got a problem with truncation that I can't seem to solve.
In the example, suppose the string ##
is the image. So my string looks something like Hello world! ##
. Tail truncation is set on the paragraph style.
Now, if the space is constrained, the text is truncated with ellipsis (which is what I want). But unfortunately the image is truncated as well.
So the result is something like:
Hello w...
but I'd like it to look like:
Hello...##
That is, I want the image attachment to not get truncated, it should always be visible.
The reason for the attachment is that I want the image to always be at the end of the string, so when the text is short the image is at the end and when the text wraps to multiple lines I also want the image to be at the end. Trying to manually position the image "on the outside" wouldn't work as the text then wouldn't get truncated correctly.
So, is there a way to tell NSAttributedString
not to truncate the image?
Example code that produces the attributed string:
NSString *title;
NSMutableAttributedString *attributedString;
NSMutableParagraphStyle *paragraph;
NSDictionary *attributes;
NSTextAttachment *attachment;
paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraph.hyphenationFactor = 1.0;
paragraph.lineBreakMode = NSLineBreakByTruncatingTail;
attributes = @{
NSForegroundColorAttributeName : [self titleTextColor],
NSParagraphStyleAttributeName : paragraph,
};
title = @"Hello world!";
attributedString = [[NSMutableAttributedString alloc] initWithString:title
attributes:attributes];
attachment = [[NSTextAttachment alloc] init];
attachment.image = [UIImage imageNamed:@"myImage"];
[attributedString appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]];
[attachment release];
self.titleLabel.attributedText = attributedString;
[attributedString release];
[paragraph release];
Edit: A vital part of this (which gets lost in the description above a bit) is that this solution needs to work for multiline texts.
This is not easily achievable. You could set the paragraph style to NSLineBreakByTruncatingMiddle
, but then the result would be that the last line is truncated in the middle ("Hel...rld!##"
)
So you have a few options.
UILabel
does not use TextKit to render text, it uses CoreText, thus making things a little harder. I would recommend dropping the UILabel
entirely and going with a custom UIView
implementation with Text Kit backing. You can find here a small example of a view drawing text using Text Kit, resulting in a view similar to a label. Now you can get bounding boxes of the drawn glyphs, and place the image correctly.Neither option is perfect. You have not mentioned what the image is and why you need it at the end of the last line. I would probably go with option #1 and change the design a little, although the Text Kit option is not that difficult to implement.
I do not think that you get the desired results with "tricks". You have to do the real work: Subclass NSTextContainer
and overwrite -lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect:
. That includes setting up your own text stack.
The code is too long to be posted here. But there are some samples in documentation. (The documentation of OS X is richer, IIRC. There are differences, but you can use it for a basic understanding of the parts.) So this answer is still a pointer.
As you are living in Munich, I assume that you understand german. Therefore I want to mention that there is a code sample in the second part of my book, chapter 6, for a view that layouts text around a hole in the middle. You can do the same by sparing out a rect at the end.
Hope that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With