没有自动换行的多行 UILabel?

dev*_*os1 5 cocoa-touch word-wrap uilabel ios

是否有可能有一个UILabel由多个\n分隔线组成的线,使其宽度 > 标签宽度被截断而不是包裹?

假设我有一些类似以下的文本:

  1. 这是一个非常长的第一行文本,太长而无法水平放置
  2. 短线
  3. 另一条短线

我希望这出现在我的UILabel样子:

1. 这是一个很长的第一行文本...
2. 短线
3. 另一条短线

然而,发生的事情是我得到了这个:

1. 这是一段很长的第一行文字  
太长而无法水平放置
2. 短线...

第三行正在被切断。我已将行数设置为3,但它仍在包装第一条长行。我在标签上设置换行符属性的内容似乎并不重要——它总是包含第一行。有什么办法可以防止完全包裹在标签上?

rde*_*mar 3

我认为这对于您可以应用于标签的任何设置都是不可能的。一种方法是将字符串分成单独的行,截断任何需要它的行,以便它(添加省略号)适合一行,然后用换行符将字符串放回一起。像这样的东西应该适用于任意数量的行,

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (nonatomic) CGFloat ellipsisWidth;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *text = @"This is a really long first line of text that is too long to fit horizontally\nShort line\nAnother short line";
    NSString *ellipsis = @"...";
    self.ellipsisWidth = [ellipsis sizeWithAttributes:@{NSFontAttributeName:self.label.font}].width;

    __block NSMutableString *truncatedString = [@"" mutableCopy];
    [text enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
        [truncatedString appendFormat:@"%@\n", [self oneLineOfString:line withFont:self.label.font]];
    }];
    NSString *finalString = [truncatedString stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
    self.label.numberOfLines = 0;
    self.label.text = finalString;
}

-(NSString *)oneLineOfString:(NSString *) aLine withFont:(UIFont *) font {
    __block NSString *singleLine = nil;
    __block NSString *lastFragment;

    [aLine enumerateSubstringsInRange:NSMakeRange(0, aLine.length) options:NSStringEnumerationByWords usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        NSString *textFragment = [aLine substringToIndex:(substringRange.location + substringRange.length)];
        CGRect textRect = [textFragment boundingRectWithSize:CGSizeMake(CGFLOAT_MAX ,CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:font} context:nil];
        if (textRect.size.width >= self.label.bounds.size.width - self.ellipsisWidth) {
            singleLine = [lastFragment stringByAppendingString:@"..."];
            *stop = YES;
        }
        lastFragment = textFragment;
    }];
    if (!singleLine) singleLine = aLine; // it doesn't need to be truncated, so return the passed in line
    return singleLine;
}
Run Code Online (Sandbox Code Playgroud)

如果你想按字符而不是按单词截断,可以将 NSStringEnumerationByComposeCharacterSequences 而不是 NSStringEnumerationByWords 传递给 enumerateSubstringsInRange:options:usingBlock: 的 options 参数。

当然,你也可以用简单的方法来做;将 3 个标签堆叠在一起,并为每个标签提供一行文本:)