我试图让UILabel缩小,以免词语截断到下一行。不只是在文本区域末尾截断文本。
如果我有一个50x100的盒子,我想要输入像#34; American"在25.0pt的方框中,我最终得到了:
50px
-------
|Ameri- |
|can |
|Beauty | 100px
| |
-------
在这种情况下,文字缩小似乎没有做任何事情,因为它仍然适合UILabel框架。当文本非常长,如Willie Wonka的巧克力工厂"时,它的效果非常好,但我不想截断文字。
这是该场景中的理想输出:
50px
--------
[American|
|Beauty | 100px
| |
| |
| |
--------
任何建议都会超级适用!
编辑:解决方案
由于下面答案中的建议,我最终做了以下事情。它很棒!
- (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;
}
答案 0 :(得分:4)
只是添加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
}
}
}
答案 1 :(得分:2)
我可以想到没有直接内置的东西。所以我建议:
按[NSCharacterSet +whitespaceAndNewlineCharacterSet]
和[NSString -componentsSeparatedByCharactersInSet:]
将字符串拆分为组件。我考虑过推荐更高级别的NSLinguisticTagger
以获得完整的单词,但这样就不会允许像结尾的单词这样的内容。
在这些词中,使用UIKit添加NSString -sizeWithAttributes:
(在iOS 7下)或-sizeWithFont:
(在6或以下)找到排版最大的词。当你缩小字体大小时,你会假设最大值仍然是最大的,我认为这总是正确的,因为Apple没有做出激进的字体提示。
如果该字的宽度已经不如您的视图宽度,那么您就完成了。只需显示字符串。
否则使用快速二进制搜索,反复查询大小,直到找到你认为合适的精度所需的较小字体大小(0.1分对我来说听起来很合理,但你明白了)。然后以该大小显示整个字符串。
答案 2 :(得分:0)
我做了一个UILabel的Swift扩展。在设置边界和文本后,只需将方法调用到标签即可。
extension UILabel {
func fitToAvoidWordWrapping(){
// adjusts the font size to avoid long word to be wrapped
// get text as NSString
let text = self.text ?? "" as NSString
// get array of words separate by spaces
let words = text.componentsSeparatedByString(" ") as! [NSString]
// 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 wordSize = word.sizeWithAttributes([NSFontAttributeName : self.font])
let wordWidth = wordSize.width
// check if this word is the largest one
if wordWidth > largestWordWidth{
largestWordWidth = wordWidth
largestWord = word
}
}
// now that I have the largest word, reduce the label's font size until it fits
while largestWordWidth > self.bounds.width && self.font.pointSize > 1{
// reduce font and update largest word's width
self.font = self.font.fontWithSize(self.font.pointSize - 1)
let largestWordSize = largestWord.sizeWithAttributes([NSFontAttributeName : self.font])
largestWordWidth = largestWordSize.width
}
}
}
答案 3 :(得分:0)
SWIFT 3上述扩展的翻译。奇迹般有效!
extension UILabel {
func fitToAvoidWordWrapping(){
// adjusts the font size to avoid long word to be wrapped
// get text as NSString
let text = self.text ?? ("" as NSString) as String
// get array of words separate by spaces
let words = text.components(separatedBy: " ")
// 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 wordSize = word.size(attributes: [NSFontAttributeName : self.font])
let wordWidth = wordSize.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 > self.bounds.width && self.font.pointSize > 1{
// reduce font and update largest word's width
self.font = self.font.withSize(self.font.pointSize - 1)
let largestWordSize = largestWord.size(attributes: [NSFontAttributeName : self.font])
largestWordWidth = largestWordSize.width
}
}
}