【发布时间】:2015-03-20 22:00:50
【问题描述】:
在我的应用程序中,如果文本输入很大,我需要在文本视图中设置 Read more。所以我的方法是找到适合文本视图的字符串范围并将 See More 添加到它。有什么办法在 Swift 中实现它。要求是模拟 read more 选项,以便在 facebook 等点击时以详细视图显示完整文本。
【问题讨论】:
标签: ios swift nsstring uitextview nsrange
在我的应用程序中,如果文本输入很大,我需要在文本视图中设置 Read more。所以我的方法是找到适合文本视图的字符串范围并将 See More 添加到它。有什么办法在 Swift 中实现它。要求是模拟 read more 选项,以便在 facebook 等点击时以详细视图显示完整文本。
【问题讨论】:
标签: ios swift nsstring uitextview nsrange
您要查找的函数是CTFramesetterSuggestFrameSizeWithConstraints。从本质上讲,它允许您找出适合某个框架的字符数。您可以使用该数字切断当前文本并插入一个按钮。
我为 UILabel 的子类编写了这个函数的实现:
- (NSInteger)numberOfCharactersThatFitLabel {
// Create an 'CTFramesetterRef' from an attributed string
CTFontRef fontRef = CTFontCreateWithName((CFStringRef)self.font.fontName, self.font.pointSize, NULL);
NSDictionary *attributes = [NSDictionary dictionaryWithObject:(__bridge id)fontRef forKey:(id)kCTFontAttributeName];
CFRelease(fontRef);
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:self.text attributes:attributes];
CTFramesetterRef frameSetterRef = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);
// Get a suggested character count that would fit the attributed string
CFRange characterFitRange;
CTFramesetterSuggestFrameSizeWithConstraints(frameSetterRef, CFRangeMake(0,0), NULL, CGSizeMake(self.bounds.size.width, self.numberOfLines*self.font.lineHeight), &characterFitRange);
CFRelease(frameSetterRef);
return (NSInteger)characterFitRange.length;
}
Here's a bog post 用于将随机文本截断到指定行数并附加“查看更多”文本的完整实现。
【讨论】:
kgaidis 出色答案的粗略快速翻译。
extension UILabel {
func numberOfCharactersThatFitLabel() -> Int {
let fontRef = CTFontCreateWithName(self.font.fontName as CFStringRef, self.font.pointSize, nil)
let attributes = NSDictionary(dictionary: [kCTFontAttributeName : fontRef])
let attributeString = NSAttributedString(string: text!, attributes: attributes as? [String : AnyObject])
let frameSetterRef = CTFramesetterCreateWithAttributedString(attributeString as CFAttributedStringRef)
var characterFitRange:CFRange
CTFramesetterSuggestFrameSizeWithConstraints(frameSetterRef, CFRangeMake(0, 0), nil, CGSizeMake(bounds.size.width, CGFloat(numberOfLines)*font.lineHeight), &characterFitRange)
return characterFitRange.length
}
}
【讨论】:
这是 Swift 4 UITextView 扩展
extension UITextView {
func numberOfCharactersThatFitTextView() -> Int {
let fontRef = CTFontCreateWithName(font!.fontName as CFString, font!.pointSize, nil)
let attributes = [kCTFontAttributeName : fontRef]
let attributedString = NSAttributedString(string: text!, attributes: attributes as [NSAttributedStringKey : Any])
let frameSetterRef = CTFramesetterCreateWithAttributedString(attributedString as CFAttributedString)
var characterFitRange: CFRange = CFRange()
CTFramesetterSuggestFrameSizeWithConstraints(frameSetterRef, CFRangeMake(0, 0), nil, CGSize(width: bounds.size.width, height: bounds.size.height), &characterFitRange)
return Int(characterFitRange.length)
}
}
如果文本超出预期,可以尝试调整CTFramesetterSuggestFrameSizeWithConstraints函数参数中的高度值。
【讨论】:
这有点复杂,因为有些字母比其他字母宽。但是您可以使用sizeWithAttributes-方法检查字符串的宽度:
var yourString: String = textField.text
let myString: NSString = originalString as NSString
//Set your font and add attributes if needed.
let stringSize: CGSize = myString.sizeWithAttributes([NSFontAttributeName: yourFont])
现在您会收到一个 CGSize,您可以检查宽度是否比您的文本字段宽。
if(sizeOfYourTextfield < stringSize){
//String is too large for your UITextField
}
【讨论】: