nor*_*rry 5 objective-c interface-builder uilabel ios
我正在尝试缩小UILabel,以使单词不会截断到下一行。不仅仅是文本在文本区域的末尾被截断。
如果我有一个50x100的盒子,而我想在25.0pt的盒子里放类似“美国”的东西,我最终会得到:
50px
-------
|Ameri- |
|can |
|Beauty | 100px
| |
-------
Run Code Online (Sandbox Code Playgroud)
在这种情况下,文本收缩似乎没有任何作用,因为它仍然适合UILabel框架。当文本很长时,例如“ Willie Wonka的Chocolate Factory”,它会很好地工作,但是我不希望单词被截断。
在这种情况下,这是理想的输出:
50px
--------
[American|
|Beauty | 100px
| |
| |
| |
--------
Run Code Online (Sandbox Code Playgroud)
任何建议将不胜感激!
编辑:解决方案
由于以下答案中的建议,这就是我最后要做的事情。效果很好!
- (CGFloat) calculateFromUILabel:(UILabel *)label
{
NSString *stringToMeasure = label.text;
NSLog(@"FontSizeMeasurement.calculateFromUILabel() %@", stringToMeasure);
NSRange range = NSMakeRange(0, 1);
NSAttributedString *attributedString = label.attributedText;
NSDictionary *attributes = [attributedString attributesAtIndex:0 effectiveRange:&range];
NSMutableCharacterSet *characterSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy];
[characterSet addCharactersInString:@"-"];
NSArray *words = [stringToMeasure componentsSeparatedByCharactersInSet:characterSet];
CGSize maxSize = CGSizeZero;
NSMutableAttributedString *maxWidthString = nil;
for(int i = 0; i < words.count; i++) {
NSString *word = words[i];
CGSize wordSize = [word sizeWithAttributes:attributes];
if(wordSize.width > maxSize.width) {
maxSize = wordSize;
maxWidthString = [[NSMutableAttributedString alloc] initWithString:word attributes:attributes];
}
}
UIFont *font = [label.font copy];
while(maxSize.width > self.maxWidth) {
font = [font fontWithSize:(font.pointSize-0.1)];
[maxWidthString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, maxWidthString.length)];
maxSize = [maxWidthString size];
}
return font.pointSize;
}
Run Code Online (Sandbox Code Playgroud)
只是添加Swift 4版本+添加一个后卫只能使用adjustsFontSizeToFitWidth true来做到这一点,因为使用false的用户不会想用长词来形容。
extension UILabel {
// Adjusts the font size to avoid long word to be wrapped
func fitToAvoidWordWrapping() {
guard adjustsFontSizeToFitWidth else {
return // Adjust font only if width fit is needed
}
guard let words = text?.components(separatedBy: " ") else {
return // Get array of words separate by spaces
}
// I will need to find the largest word and its width in points
var largestWord: NSString = ""
var largestWordWidth: CGFloat = 0
// Iterate over the words to find the largest one
for word in words {
// Get the width of the word given the actual font of the label
let wordWidth = word.size(withAttributes: [.font: font]).width
// check if this word is the largest one
if wordWidth > largestWordWidth {
largestWordWidth = wordWidth
largestWord = word as NSString
}
}
// Now that I have the largest word, reduce the label's font size until it fits
while largestWordWidth > bounds.width && font.pointSize > 1 {
// Reduce font and update largest word's width
font = font.withSize(font.pointSize - 1)
largestWordWidth = largestWord.size(withAttributes: [.font: font]).width
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想不出任何直接内置的东西。所以我建议:
[NSCharacterSet +whitespaceAndNewlineCharacterSet]通过和将字符串拆分为多个部分[NSString -componentsSeparatedByCharactersInSet:]。我考虑过建议更高级别的人NSLinguisticTagger输出整个单词,但这不允许像末尾带有冒号的单词这样的东西。
在这些单词中,使用 UIKit 添加NSString -sizeWithAttributes:(在 iOS 7 下)或-sizeWithFont:(在 6 或更低版本下)查找排版上最大的单词。你会假设当你缩小字体大小时,最大的仍然是最大的,我认为这永远是正确的,因为苹果不会做激进的字体提示。
如果该单词的宽度已经小于您视图的宽度,那么您就完成了。只需显示字符串即可。
否则,请使用快速二分搜索,反复查询大小,直到找到所需的较小字体大小,且精度不超过您认为合适的精度(0.1 点对我来说听起来很合理,但您明白了)。然后以该大小显示整个字符串。
| 归档时间: |
|
| 查看次数: |
1452 次 |
| 最近记录: |