【问题标题】:How do I truncate a string within a string in a UILabel?如何截断 UILabel 中字符串中的字符串?
【发布时间】:2012-12-04 02:13:26
【问题描述】:

假设我有The Dark Knight Rises at 7:45pm,我需要将其放入固定宽度的 UILabel(适用于 iPhone)中。我如何将其截断为“The Dark Knight Ris... at 7:45pm”而不是“The Dark Knight Riss at 7:4...”?

【问题讨论】:

    标签: iphone objective-c ios uikit views


    【解决方案1】:

    UILabel 有这个属性:

    @property(nonatomic) NSLineBreakMode lineBreakMode;
    

    您可以通过将其设置为 NSLineBreakByTruncatingMiddle 来启用该行为。

    编辑

    我不明白你只想截断字符串的一部分。然后阅读:

    如果您只想将换行模式应用于文本的一部分,请创建一个具有所需样式信息的新属性字符串并将其与标签相关联。如果您不使用样式文本,则此属性适用于 text 属性中的整个文本字符串。

    示例

    所以甚至还有一个设置段落样式的类:NSParagraphStyle,它也有可变版本。
    因此,假设您有一个要应用该属性的范围:

    NSRange range=NSMakeRange(i,j);
    

    您必须创建一个 NSMutableParagraphStyle 对象并将其 lineBreakMode 设置为 NSLineBreakByTruncatingMiddle。注意您还可以设置很多其他参数。所以让我们这样做:

    NSMutableParagraphStyle* style= [NSMutableParagraphStyle new];
    style.lineBreakMode= NSLineBreakByTruncatingMiddle;
    

    然后在该范围内为标签的属性文本添加该属性。属性文本属性是 NSAttributedString,而不是 NSMutableAttributedString,因此您必须创建一个 NSMutableAttributedString 并将其分配给该属性:

    NSMutableAttributedString* str=[[NSMutableAttributedString alloc]initWithString: self.label.text];
    [str addAttribute: NSParagraphStyleAttributeName value: style range: range];
    self.label.attributedText= str;
    

    请注意,NSAttributedString 还有很多其他属性,请查看here

    【讨论】:

    • 不过,这并不能回答问题。那会在最后截断,但我只想截断字符串的一个子集。
    • @Aaron 如果你想要动态截断,你必须写一个正则表达式。
    • 你也可以不用正则表达式。 @Aaron 你需要一个例子吗?
    • 您能否确认此解决方案有效?从 wwdc 2012 会议adcdownload.apple.com//wwdc_2012/wwdc_2012_session_pdfs/… 的幻灯片 #143 中,看起来段落样式被应用于整个段落,并且当您只有一个段落时,范围将几乎无用。我尝试了 NSLineBreakByTruncatingMiddle 并且它确实在中间截断但也可以指定截断位置?
    • Ramy Al Zuhouri,它在 IOS 8 SDK 中不起作用。我想要例如“Some very very long string(10)”被截断为“Some ver...(10)”。你能写一个例子吗?
    【解决方案2】:

    您必须设置lineBreakMode。您可以从 Interface Builder 或以编程方式执行此操作,如下所示

    label.lineBreakMode = NSLineBreakByTruncatingMiddle;
    

    请注意,自 iOS 5 起,此类属性的类型已从 UILineBreakMode 更改为 NSLineBreakMode

    【讨论】:

      【解决方案3】:

      我的第一个想法是两个标签并排固定宽度,但我假设你已经排除了一些未说明的原因。或者,手动计算截断,像这样 ...

      - (NSString *)truncatedStringFrom:(NSString *)string toFit:(UILabel *)label
                                atPixel:(CGFloat)pixel atPhrase:(NSString *)substring {
      
          // truncate the part of string before substring until it fits pixel
          // width in label
      
          NSArray *components = [string componentsSeparatedByString:substring];
          NSString *firstComponent = [components objectAtIndex:0];
          CGSize size = [firstComponent sizeWithFont:label.font];
      
          NSString *truncatedFirstComponent = firstComponent;
      
          while (size.width > pixel) {
              firstComponent = [firstComponent substringToIndex:[firstComponent length] - 1];
              truncatedFirstComponent = [firstComponent stringByAppendingString:@"..."];
              size = [truncatedFirstComponent sizeWithFont:label.font];
          }
      
          NSArray *newComponents = [NSArray arrayWithObjects:truncatedFirstComponent, [components lastObject], nil];
          return [newComponents componentsJoinedByString:substring];
      }
      

      这样称呼它:

      UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 160, 21)];
      NSString *string = @"The Dark Knight Rises at 7:45pm";
      NSString *substring = @"at";
      CGFloat pix = 120.0;
      NSString *result = [self truncatedStringFrom:string toFit:label atPixel:120.0 atPhrase:@"at"];
      
      label.text = result;
      

      这会生成:@"The Dark Kni...at 7:45pm"

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-12
        • 1970-01-01
        • 2011-06-15
        • 2011-02-16
        相关资源
        最近更新 更多