我有一个带附加图像的属性字符串(NSTextAttachment
)。这样做没问题,但是我遇到了截断问题,我似乎无法解决。
在示例中,假设字符串##
是图像。所以我的字符串看起来像Hello world! ##
。尾部截断是在段落样式上设置的。
现在,如果空间受到限制,文本将被省略(这是我想要的)。但不幸的是,图像也被截断了。
结果如下:
Hello w...
但我希望它看起来像:
Hello...##
也就是说,我希望图像附件不会被截断,它应该始终可见。
附件的原因是我希望图像始终位于字符串的末尾,所以当文本很短时,图像就在最后,当文本换行到多行时,我也想要图像到在最后。尝试手动将图像“放在外面”不会起作用,因为文本不会被正确截断。
那么,有没有办法告诉NSAttributedString
不截断图像?
生成属性字符串的示例代码:
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];
编辑:这一点的重要部分(在上面的描述中丢失了一点)是这个解决方案需要适用于多行文本。
答案 0 :(得分:3)
这不容易实现。您可以将段落样式设置为NSLineBreakByTruncatingMiddle
,但结果将是最后一行在中间截断("Hel...rld!##"
)
所以你有几个选择。
UILabel
不使用TextKit来渲染文本,但它使用了CoreText,从而使事情变得更加困难。我建议完全删除UILabel
并使用Text Kit支持自定义UIView
实现。您可以使用Text Kit找到here视图绘图文本的一个小示例,从而生成类似于标签的视图。现在,您可以获得绘制的字形的边界框,并正确放置图像。这两种选择都不完美。你还没有提到图像是什么以及为什么你需要它在最后一行的末尾。我可能会使用选项#1并稍微更改设计,尽管Text Kit选项并不难实现。
答案 1 :(得分:3)
我不认为你用“技巧”得到了预期的结果。你必须做真正的工作:子类NSTextContainer
并覆盖-lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect:
。这包括设置自己的文本堆栈。
代码太长,无法在此处发布。但是文档中有一些示例。 (OS X的文档更丰富,IIRC。存在差异,但您可以使用它来基本了解这些部分。)所以这个答案仍然是一个指针。
当你住在慕尼黑时,我认为你懂德语。因此,我想提一下,在我的书的第二部分第6章中有一个代码示例,用于在中间的孔周围布局文本的视图。你可以通过在最后省略一个矩形来做同样的事。
希望有所帮助!
答案 2 :(得分:0)
我想一种方法是获取完整字符串的长度,截断字符串的长度,然后使用Hello world!
生成新的NSString,截断差值+ 3,然后添加...##
最后。
它适合你的目的吗?
答案 3 :(得分:0)
当您在UILabel中显示它时,您设置了
self.titleLabel.lineBreakMode = NSLineBreakByTruncatingMiddle
答案 4 :(得分:0)
最近我也遇到了类似的情况,这是我最终找到的解决方案,在我的情况下效果很好。
我有一个UILabel,我想显示一个字符串,后跟一个图像。但是,如果这种组合超出了UILabel的宽度,我必须截断字符串,然后将图像附加在末尾。
我将在下面发布我的解决方案,这将对某人有所帮助。
/// Provide a single line attibuted string with the image at the end of the string, and will truncate the string if the whole composision will exceed the frame size.
/// - Parameters:
/// - string: The string which we are going to append the image
/// - rect: The UILabel rect of the string
/// - font: The Font to use in the attributed string
/// - imageName: The image name
/// - imageOrigin: The image location
/// - Returns: The attibuted string with the image at the end. This string will be truncated if needed.
private func getAttributedStringWithImage(string: String,
rect: CGSize,
font: UIFont,
imageName: String,
imageOrigin: CGPoint) -> NSAttributedString {
// creating image to append at the end of the string
let iconImage = UIImage(named: imageName)!
let icon = NSTextAttachment()
icon.bounds = CGRect(x: imageOrigin.x, y: imageOrigin.y, width: iconImage.size.width, height: iconImage.size.height)
icon.image = iconImage
let iconString = NSAttributedString(attachment: icon)
// we will calculate the "attributed string length with image at the end" to deside whether we need to truncate
// the string to append the image or not by looping the string
var newStr = ""
for char in string {
newStr += String(char)
let attStr = NSMutableAttributedString(string: (newStr + "..."), attributes: [ .font: font, .kern: 0.0 ])
let stringRect = attStr.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: rect.height),
options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
if stringRect.width + imageOrigin.x + iconImage.size.width + 5 > rect.width {
newStr += "..."
break
}
}
let titleString = NSMutableAttributedString(string: newStr, attributes: [ .font: font, .kern: 0.0 ])
titleString.append(iconString)
return titleString
}
并这样称呼它:
let attributedText = getAttributedStringWithImage(string: contactEmailOrNumber,
rect: self.titleLabel.frame.size,
font: UIFont(name: "FontName-Bold", size: xx.0)!,
imageName: "ImageName",
imageOrigin: CGPoint(x: 6, y: -3))