I want to set UILabel to character wrap + truncate tail. If I only set it to truncate tail, it breaks lines for word wrapping. How can I achieve this?"
NSLineBreakByCharWrapping | NSLineBreakByTruncatingTail
I try it but failed
I want to set UILabel to character wrap + truncate tail. If I only set it to truncate tail, it breaks lines for word wrapping. How can I achieve this?"
NSLineBreakByCharWrapping | NSLineBreakByTruncatingTail
I try it but failed
On
+ (void)addEllipsisAtLabel:(nonnull UILabel *)label ellipsis:(nonnull NSString *)ellipsis {
if (label == nil || label.text == nil || label.text.length == 0 || ellipsis == nil) return;
if (label.numberOfLines <= 1) return;
if (!(label.lineBreakMode == NSLineBreakByCharWrapping)) return;
// int lines = [THISUTILCLASS numberOfLine:label content:label.text];
CGSize maxSize = CGSizeMake(label.frame.size.width, CGFLOAT_MAX);
NSInteger lines = [THISUTILCLASS numberOfLinesForString: label.text size:maxSize font:label.font];
NSUInteger index = label.text.length;
while (lines > label.numberOfLines) {
NSString *subStr = [label.text substringToIndex: index];
if (!subStr) {
return;
}
NSString *combineStr = [NSString stringWithFormat:@"%@%@", subStr, ellipsis];
// int newLines = [THISUTILCLASS numberOfLine:label content:combineStr];
NSInteger newLines = [THISUTILCLASS numberOfLinesForString: combineStr size:maxSize font:label.font];
if (newLines > label.numberOfLines) {
if (--index <= 0) return;
} else {
label.text = combineStr;
return;
}
}
}
+ (int)numberOfLine:(nonnull UILabel *)label content:(nonnull NSString *)content {
if (label == nil || content == nil || content.length == 0) return 0;
CGSize maxSize = CGSizeMake(label.frame.size.width, CGFLOAT_MAX);
CGRect rect = [content boundingRectWithSize:maxSize
options:NSStringDrawingUsesLineFragmentOrigin | label.lineBreakMode
attributes:@{NSFontAttributeName:label.font}
context:nil];
return (int)(ceil((rect.size.height / label.font.lineHeight)));
}
+ (NSInteger)numberOfLinesForString:(nonnull NSString *)string size:(CGSize)size font:(nonnull UIFont *)font {
if (string == nil || font == nil) return 0;
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:string attributes:@{NSFontAttributeName: font}];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:size];
textContainer.lineBreakMode = NSLineBreakByWordWrapping;
textContainer.maximumNumberOfLines = 0;
textContainer.lineFragmentPadding = 0;
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[layoutManager setTextStorage:textStorage];
[layoutManager addTextContainer:textContainer];
NSInteger numberOfLines = 0;
NSUInteger index = 0;
NSRange lineRange = NSMakeRange(0, 0);
while (index < [layoutManager numberOfGlyphs]) {
[layoutManager lineFragmentRectForGlyphAtIndex:index effectiveRange:&lineRange];
index = NSMaxRange(lineRange);
numberOfLines++;
}
return numberOfLines;
}
I would consider looking into the
numberOfLinesproperty onUILabel. I am not sure the exact behavior without testing this, but if you set thenumberOfLines = 2and then thelineBreakMode = .byTruncatingTailyou might be able to get this functionality by sacrificing a dynamic number of lines.