当 a 的文本UILabel
被截断时,默认插入 3 个点。是否可以更改这些字符或禁用它们?
6 回答
我已经编写了一个自定义截断类,您可以随时将其弹出到您的代码中。只需使用下面的这种方法。如果发生截断,它将返回 true,如果您只想使用标签默认帧宽度,则 MaxWidth 可以保留为 0。将 maxWidth 设置为小于帧宽度的值,以在其帧范围内缩短它。
Swift 2(带有一些 swift 3 注释用于转换)
用法:
Truncater.replaceElipsis(forLabel: label, withString: "???")
let didTruncate = Truncater.replaceElipsis(forLabel: label, withString: "1234", andMaximumWidth: 50) //maxWidth is not number of chars, but label width in CGFloat
班级:
import UIKit
class Truncater {
class func replaceElipsis(forLabel label:UILabel, withString replacement:String) -> Bool {
return replaceElipsis(forLabel: label, withString: replacement, andMaximumWidth:0)
}
class func replaceElipsis(forLabel label:UILabel, withString replacement:String, andMaximumWidth width:CGFloat) -> Bool {
if(label.text == nil){
return false
}
let origSize = label.frame;
var useWidth = width
if(width <= 0){
useWidth = origSize.width //use label width by default if width <= 0
}
label.sizeToFit()
let labelSize = label.text!.sizeWithAttributes([NSFontAttributeName: label.font]) //.size(attributes: [NSFontAttributeName: label.font]) for swift 3
if(labelSize.width > useWidth){
let original = label.text!;
let truncateWidth = useWidth;
let font = label.font;
let subLength = label.text!.characters.count
var temp = label.text!.substringToIndex(label.text!.endIndex.advancedBy(-1)) //label.text!.substring(to: label.text!.index(label.text!.endIndex, offsetBy: -1)) for swift 3
temp = temp.substringToIndex(temp.startIndex.advancedBy(getTruncatedStringPoint(subLength, original:original, truncatedWidth:truncateWidth, font:font, length:subLength)))
temp = String.localizedStringWithFormat("%@%@", temp, replacement)
var count = 0
while temp.sizeWithAttributes([NSFontAttributeName: label.font]).width > useWidth {
count+=1
temp = label.text!.substringToIndex(label.text!.endIndex.advancedBy(-(1+count)))
temp = temp.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) //remove this if you want to keep whitespace on the end
temp = String.localizedStringWithFormat("%@%@", temp, replacement)
}
label.text = temp;
label.frame = origSize;
return true;
}
else {
label.frame = origSize;
return false
}
}
class func getTruncatedStringPoint(splitPoint:Int, original:String, truncatedWidth:CGFloat, font:UIFont, length:Int) -> Int {
let splitLeft = original.substringToIndex(original.startIndex.advancedBy(splitPoint))
let subLength = length/2
if(subLength <= 0){
return splitPoint
}
let width = splitLeft.sizeWithAttributes([NSFontAttributeName: font]).width
if(width > truncatedWidth) {
return getTruncatedStringPoint(splitPoint - subLength, original: original, truncatedWidth: truncatedWidth, font: font, length: subLength)
}
else if (width < truncatedWidth) {
return getTruncatedStringPoint(splitPoint + subLength, original: original, truncatedWidth: truncatedWidth, font: font, length: subLength)
}
else {
return splitPoint
}
}
}
目标 C
+ (bool) replaceElipsesForLabel:(UILabel*) label With:(NSString*) replacement MaxWidth:(float) width
班级:
//=============================================Header=====================================================
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface CustomTruncater : NSObject
+ (bool) replaceElipsesForLabel:(UILabel*) label With:(NSString*) replacement MaxWidth:(float) width;
@end
//========================================================================================================
#import "CustomTruncater.h"
@implementation CustomTruncater
static NSString *original;
static float truncateWidth;
static UIFont *font;
static int subLength;
+ (bool) replaceElipsesForLabel:(UILabel*) label With:(NSString*) replacement MaxWidth:(float) width {
CGRect origSize = label.frame;
float useWidth = width;
if(width <= 0)
useWidth = origSize.size.width; //use label width by default if width <= 0
[label sizeToFit];
CGSize labelSize = [label.text sizeWithFont:label.font];
if(labelSize.width > useWidth) {
original = label.text;
truncateWidth = useWidth;
font = label.font;
subLength = label.text.length;
NSString *temp = [label.text substringToIndex:label.text.length-1];
temp = [temp substringToIndex:[self getTruncatedStringPoint:subLength]];
temp = [NSString stringWithFormat:@"%@%@", temp, replacement];
int count = 0;
while([temp sizeWithFont:label.font].width > useWidth){
count++;
temp = [label.text substringToIndex:(label.text.length-(1+count))];
temp = [temp stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; //remove this if you want to keep whitespace on the end
temp = [NSString stringWithFormat:@"%@%@", temp, replacement];
}
label.text = temp;
label.frame = origSize;
return true;
}
else {
label.frame = origSize;
return false;
}
}
+ (int) getTruncatedStringPoint:(int) splitPoint {
NSString *splitLeft = [original substringToIndex:splitPoint];
subLength /= 2;
if(subLength <= 0)
return splitPoint;
if([splitLeft sizeWithFont:font].width > truncateWidth){
return [self getTruncatedStringPoint:(splitPoint - subLength)];
}
else if ([splitLeft sizeWithFont:font].width < truncateWidth) {
return [self getTruncatedStringPoint:(splitPoint + subLength)];
}
else {
return splitPoint;
}
}
@end
正如Javanator所说,您必须自己进行截断。您应该使用
sizeWithFont:forWidth:lineBreakMode:
UIKit 添加到NSString
类的消息来获取具有特定字体的字符串的宽度。这将处理所有类型的字体。
看-[UILabel setLineBreakMode:]
和UILineBreakModeCharacterWrap
。的默认值-[UILabel lineBreakMode]
是UILineBreakModeTailTruncation
,这会导致省略号在末尾。
您还可以设置
[lbl setAdjustsFontSizeToFitWidth:YES];
这样就不需要截断文本,您可以在label
.
我想提供一个更 Swifty 版本的 Fonix 之前提供的并使用 Swift 5 语法。我还决定将这些函数编写为UILabel
.
extension UILabel {
func replaceEllipsis(withString replacement: String, andMaximumWidth width: CGFloat = 0) -> Bool {
if let labelText = self.text, let font = self.font {
let origSize = self.frame
var useWidth = width
if width <= 0 {
useWidth = origSize.width // use label width by default if width <= 0
}
self.sizeToFit()
let labelSize = labelText.size(withAttributes: [NSAttributedString.Key.font: font])
if labelSize.width > useWidth {
let truncateWidth = useWidth
let subLength = labelText.count
var newText = String(labelText[..<labelText.index(labelText.endIndex, offsetBy: -1)])
newText = String(newText[..<newText.index(labelText.startIndex, offsetBy: getTruncatedStringPoint(splitPoint: subLength,
original: labelText,
truncatedWidth: truncateWidth,
font: font,
length: subLength))])
newText = String.localizedStringWithFormat("%@%@", newText, replacement)
var count = 0
while newText.size(withAttributes: [NSAttributedString.Key.font: font]).width > useWidth {
count += 1
newText = String(labelText[..<labelText.index(labelText.endIndex, offsetBy: -(1 + count))])
newText = newText.trimmingCharacters(in: NSCharacterSet.whitespaces)
newText = String.localizedStringWithFormat("%@%@", newText, replacement)
}
self.text = newText
self.frame = origSize
return true
} else {
self.frame = origSize
return false
}
} else {
return false
}
}
private func getTruncatedStringPoint(splitPoint: Int, original: String, truncatedWidth: CGFloat, font: UIFont, length: Int) -> Int {
let index = original.index(original.startIndex, offsetBy: splitPoint)
let splitLeft = String(original[..<index])
let subLength = length / 2
if subLength <= 0 {
return splitPoint
}
let width = splitLeft.size(withAttributes: [NSAttributedString.Key.font: font]).width
if width > truncatedWidth {
return getTruncatedStringPoint(splitPoint: splitPoint - subLength, original: original, truncatedWidth: truncatedWidth, font: font, length: subLength)
} else if width < truncatedWidth {
return getTruncatedStringPoint(splitPoint: splitPoint + subLength, original: original, truncatedWidth: truncatedWidth, font: font, length: subLength)
} else {
return splitPoint
}
}
}
它将按如下方式使用:
<UILabel>.replaceEllipsis(withString: " ...Read More") // if you want to use the label width
如果需要,您也可以传递自定义宽度。我在上面的例子中选择了默认宽度。
有关我在重构中使用的参考资料,以下 StackOverflow 链接很有帮助:
你为什么不编码来计算字符串的长度并在它超出视图时生成它的子字符串。或做任何你想做的事情 这是原始但有效的方法