簡體   English   中英

帶有文本附件和截斷的屬性字符串

[英]Attributed string with text attachment and truncation

我有一個帶有圖像的屬性字符串( NSTextAttachment )。 這工作正常,但我有一個截斷問題,我似乎無法解決。

在示例中,假設字符串##是圖像。 所以我的字符串看起來像Hello world! ## 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];

編輯:這個的一個重要部分(在上面的描述中有點丟失)是這個解決方案需要適用於多行文本。

這是不容易實現的。 您可以將段落樣式設置為NSLineBreakByTruncatingMiddle ,但結果將是最后一行在中間被截斷( "Hel...rld!##"

所以你有幾個選擇。

  • 您可以重新設計,以便圖像不會放置在文本的末尾。
  • 您可以自己計算字符串的結尾,截斷它並添加文本附件 - 這並不簡單。
  • 使用 iOS7 的 Text Kit 實現自定義截斷邏輯。 不幸的是,盡管許多博客和 Apple 自己的文檔都寫錯了,但UILabel沒有使用 TextKit 來呈現文本,而是使用了 CoreText,從而使事情變得有點困難。 我建議完全刪除UILabel並使用帶有 Text Kit 支持的自定義UIView實現。 您可以在此處找到一個使用 Text Kit 繪制文本視圖的小示例,從而生成類似於標簽的視圖。 現在您可以獲得繪制字形的邊界框,並正確放置圖像。

這兩種選擇都不是完美的。 您沒有在最后一行的末尾提到圖像是什么以及為什么需要它。 我可能會選擇選項 #1 並稍微更改設計,盡管 Text Kit 選項並不難實現。

我認為您不會通過“技巧”獲得預期的結果。 你必須做真正的工作:子類NSTextContainer並覆蓋-lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect: 這包括設置您自己的文本堆棧。

代碼太長,不能貼在這里。 但是文檔中有一些示例。 (OS X的文檔比較豐富,IIRC。有差異,但是可以用來對部分有基本的了解。)所以這個答案仍然是一個指針。

因為你住在慕尼黑,所以我假設你懂德語。 因此,我想提一下,在我的書的第二部分,第 6 章中,有一個代碼示例,用於在中間的孔周圍布置文本的視圖。 您可以通過在最后保留一個 rect 來做同樣的事情。

希望有幫助!

我想一種方法是獲取完整字符串的長度,截斷字符串的長度,然后使用Hello world!生成一個新的 NSString Hello world! , 截斷差值 + 3,然后在末尾添加...##

它符合你的目的嗎?

當您在 UILabel 中顯示它時,您是否設置了

self.titleLabel.lineBreakMode = NSLineBreakByTruncatingMiddle

最近我也遇到了類似的情況,這是我最終的解決方案,它在我的情況下非常有效。

我有一個 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))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM