Многострочный UILabel без переноса слов?
Возможно ли иметь UILabel
который состоит из нескольких \n
лимит строк, чтобы иметь ширину> ширину метки, которая должна быть обрезана и не обернута?
Предположим, у меня есть текст вроде следующего:
- Это действительно длинная первая строка текста, которая слишком длинна, чтобы поместиться горизонтально
- Короткая линия
- Еще одна короткая линия
Я хочу, чтобы это появилось в моем UILabel
вот так:
1. Это действительно длинная первая строка текста... 2. Короткая линия 3. Еще одна короткая очередь
Однако, что происходит, я получаю это:
1. Это действительно длинная первая строка текста это слишком долго, чтобы поместиться горизонтально 2. Короткая линия...
Третья строка обрезается. Я установил количество строк в 3
, но он все еще переносит первую длинную строку. Кажется, не имеет значения, для чего я установил свойство разрыва строки на метке - он всегда переносит эту первую строку. Есть ли какой-нибудь способ полностью обернуть этикетку?
1 ответ
Я не думаю, что это возможно при любой настройке, которую вы можете применить к своему лейблу. Один из способов сделать это - разбить строку на отдельные строки, обрезать любую нужную ей строку так, чтобы она (с добавленным многоточием) поместилась на одной строке, а затем снова поместить строку вместе с разрывами строк. Примерно так должно работать на любое количество строк,
@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;
}
Если вы хотите обрезать по символу, а не по слову, вы можете передать NSStringEnumerationByComposedCharacterSequence вместо NSStringEnumerationByWords в параметр options enumerateSubstringsInRange:options:usingBlock:.
Конечно, вы могли бы сделать это простым способом; сложите 3 надписи друг над другом и дайте каждому строчку своего текста:)