【问题标题】:Autoshrink on a UILabel with multiple lines在具有多行的 UILabel 上自动收缩
【发布时间】:2012-02-21 23:55:26
【问题描述】:

是否可以在UILabel 的多行上同时使用 autoshrink 属性?例如,2 行可用的大文本。

【问题讨论】:

  • 我更进一步回答了您的问题,因此它支持多行、可点击的标签,并且兼容 swift 5。只需在下面寻找我的答案。希望对您有所帮助!

标签: ios ios5 uilabel


【解决方案1】:

我稍微修改了接受答案的代码,使其成为UILabel 上的一个类别:

头文件:

#import <UIKit/UIKit.h>
@interface UILabel (MultiLineAutoSize)
    - (void)adjustFontSizeToFit;
@end

以及实现文件:

@implementation UILabel (MultiLineAutoSize)

- (void)adjustFontSizeToFit
{
    UIFont *font = self.font;
    CGSize size = self.frame.size;
    
    for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumFontSize; maxSize -= 1.f)
    {
        font = [font fontWithSize:maxSize];
        CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
        CGSize labelSize = [self.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
        if(labelSize.height <= size.height)
        {
            self.font = font;
            [self setNeedsLayout];
            break;
        }
    }
    // set the font to the minimum size anyway
    self.font = font;
    [self setNeedsLayout];
}

@end

【讨论】:

  • 太好了,我自己偶然发现了这个问题,这很快就解决了 :-) 只有两个注释:(1) 内部if 中的前两行子句是多余的,因为它们将在for 循环下执行。 (2) 如果还需要 UILabel 的文本垂直对齐到顶部(如果它使用的行数少于标签中实际显示的行数),则将标签的高度设置为 labelSize.height .请注意,sizeToFit 不能用于此目的,因为它会破坏以前格式化的文本并将其调整为原始字体大小。
  • 这是完美的,但 minimumFontSize 在 iOS6 中已被弃用 - 如何将其更改为使用 minimumScaleFactor 代替?
  • 正是我所需要的。谢谢。 +1
  • @bmueller:在函数顶部声明float minFontSize = self.font.pointSize * self.minimumScaleFactor;。然后将&gt;= self.minimumFontSize 替换为&gt;= minFontSize
【解决方案2】:

是的,这是可能的,尽管一开始很难弄清楚。我将更进一步,向您展示如何点击文本中的任何区域。

使用此方法,您可以拥有 UI 标签:

  • 多行友好
  • 自动收缩友好
  • 可点击友好(是的,甚至是单个字符)
  • 斯威夫特 5

第 1 步:

使 UILabel 具有“Truncate Tail”的换行符属性并设置最小字体比例

如果您不熟悉字体比例,请记住以下规则:

minimumFontSize/defaultFontSize = fontscale

在我的例子中,我希望 7.2 成为最小字体大小,而我的起始字体大小是 36。因此,7.2 / 36 = 0.2

第 2 步:

如果您不关心标签的可点击性,而只是想要一个有效的多行标签,那么您就完成了!

但是,如果您希望 标签可点击,请继续阅读...

添加我创建的以下扩展

extension UILabel {

    func setOptimalFontSize(maxFontSize:CGFloat,text:String){
        let width = self.bounds.size.width

        var font_size:CGFloat = maxFontSize //Set the maximum font size.
        var stringSize = NSString(string: text).size(withAttributes: [.font : self.font.withSize(font_size)])
        while(stringSize.width > width){
            font_size = font_size - 1
            stringSize = NSString(string: text).size(withAttributes: [.font : self.font.withSize(font_size)])
        }

        self.font = self.font.withSize(font_size)//Forcefully change font to match what it would be graphically.
    }
}

这样使用(只需将&lt;Label&gt; 替换为您的实际标签名称):

<Label>.setOptimalFontSize(maxFontSize: 36.0, text: formula)

这个扩展是必需的,因为自动收缩在标签自动收缩后不会改变标签的'font'属性,所以你必须通过与使用 . size(withAttributes) 函数,它模拟特定字体的大小。

这是必要的,因为检测标签点击位置的解决方案需要知道确切的字体大小

第 3 步:

添加以下扩展:

extension UITapGestureRecognizer {

    func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
        // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
        let layoutManager = NSLayoutManager()
        let textContainer = NSTextContainer(size: CGSize.zero)

        let mutableAttribString = NSMutableAttributedString(attributedString: label.attributedText!)
        mutableAttribString.addAttributes([NSAttributedString.Key.font: label.font!], range: NSRange(location: 0, length: label.attributedText!.length))

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = 6
        paragraphStyle.lineBreakMode = .byTruncatingTail
        paragraphStyle.alignment = .center
        mutableAttribString.addAttributes([.paragraphStyle: paragraphStyle], range: NSMakeRange(0, mutableAttribString.string.count))

        let textStorage = NSTextStorage(attributedString: mutableAttribString)

        // Configure textContainer
        textContainer.lineFragmentPadding = 0.0
        textContainer.lineBreakMode = label.lineBreakMode
        textContainer.maximumNumberOfLines = label.numberOfLines

        // Configure layoutManager and textStorage
        layoutManager.addTextContainer(textContainer)

        textStorage.addLayoutManager(layoutManager)

        let labelSize = label.bounds.size

        textContainer.size = labelSize

        // Find the tapped character location and compare it to the specified range
        let locationOfTouchInLabel = self.location(in: label)

        let textBoundingBox = layoutManager.usedRect(for: textContainer)
        //let textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
                                              //(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
        let textContainerOffset = CGPoint(x: (labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, y: (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)

        //let locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
                                                        // locationOfTouchInLabel.y - textContainerOffset.y);
        let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, y: locationOfTouchInLabel.y - textContainerOffset.y)

        let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
        print("IndexOfCharacter=",indexOfCharacter)

        print("TargetRange=",targetRange)
        return NSLocationInRange(indexOfCharacter, targetRange)
    }

}

您需要针对特定​​的多行情况修改此扩展。在我的例子中,你会注意到我使用了段落样式。

let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = 6
        paragraphStyle.lineBreakMode = .byTruncatingTail
        paragraphStyle.alignment = .center
        mutableAttribString.addAttributes([.paragraphStyle: paragraphStyle], range: NSMakeRange(0, mutableAttribString.string.count))

确保在扩展程序中将此更改为您实际使用的行距,以便一切计算正确。

第 4 步:

将gestureRecognizer添加到viewDidLoad中的标签或您认为合适的位置(只需再次将&lt;Label&gt;替换为您的标签名称:

<Label>.addGestureRecognizer(UITapGestureRecognizer(target:self, action: #selector(tapLabel(gesture:))))

这是我的 tapLabel 函数的简化示例(只需将 &lt;Label&gt; 替换为您的 UILabel 名称):

@IBAction func tapLabel(gesture: UITapGestureRecognizer) {
        guard let text = <Label>.attributedText?.string else {
            return
        }

        let click_range = text.range(of: "(α/β)")

        if gesture.didTapAttributedTextInLabel(label: <Label>, inRange: NSRange(click_range!, in: text)) {
           print("Tapped a/b")
        }else {
           print("Tapped none")
        }
    }

在我的示例中只是一个注释,我的字符串是BED = N * d * [ RBE + ( d / (α/β) ) ],所以在这种情况下我只是得到了α/β 的范围。您可以在字符串中添加“\n”以添加换行符和您想要的任何文本,然后测试它以在下一行找到一个字符串,它仍然会找到它并正确检测到点击!

就是这样!你完成了。享受多行 可点击标签。

【讨论】:

    【解决方案3】:
    extension UILabel{
    
    func adjustFont(minSize:Int, maxSize:Int){
        var newFont = self.font
        for index in stride(from: maxSize, to: minSize, by: -1) {
            newFont = UIFont.systemFont(ofSize: CGFloat(index))
            let size = CGSize(width: self.frame.width, height: CGFloat(Int.max))
            let size2 = (self.text! as NSString).boundingRect(with: size, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedStringKey.font:newFont!], context: nil).size
            if size2.height < self.frame.size.height{
                break
            }
        }
        self.font = newFont
    }
    

    }

    您还需要为 UILabel 的 numberOfLines 属性赋值。

    【讨论】:

      【解决方案4】:

      试试这个:

      在标签上设置文本属性后,子类 UILabel 或调用 adjustFontSize 方法

      override var text : String? { didSet { self.adjustFontSize() } }
      
      func adjustFontSize()
      {
          var lineCount = self.string.components(separatedBy: "\n").count - 1
          var textArray = self.string.components(separatedBy: " ")
          var wordsToCompare = 1
          while(textArray.count > 0)
          {
              let words = textArray.first(n: wordsToCompare).joined(separator: " ")
              let wordsWidth = words.widthForHeight(0, font: self.font)
              if(wordsWidth > self.frame.width)
              {
                  textArray.removeFirst(wordsToCompare)
                  lineCount += 1
                  wordsToCompare = 1
              }
              else if(wordsToCompare > textArray.count)
              {
                  break
              }
              else
              {
                  wordsToCompare += 1
              }
          }
          self.numberOfLines = lineCount + 1
      }
      

      【讨论】:

        【解决方案5】:

        我使用了@wbarksdale 的 Swift 3 解决方案,但发现中间的长词被截断了。为了保持文字完整,我不得不修改如下:

        extension UILabel {
            func adjustFontSizeToFit(minimumFontSize: CGFloat, maximumFontSize: CGFloat? = nil) {
                let maxFontSize = maximumFontSize ?? font.pointSize
                let words = self.text?.components(separatedBy: " ")
                var longestWord: String?
                if let max = words?.max(by: {$1.characters.count > $0.characters.count}) {
                    longestWord = max
                }
                for size in stride(from: maxFontSize, to: minimumFontSize, by: -CGFloat(0.1)) {
                    let proposedFont = font.withSize(size)
                    let constraintSize = CGSize(width: bounds.size.width, height: CGFloat(MAXFLOAT))
                    let labelSize = ((text ?? "") as NSString).boundingRect(with: constraintSize,
                                                                            options: .usesLineFragmentOrigin,
                                                                            attributes: [NSFontAttributeName: proposedFont],
                                                                            context: nil)
        
                    let wordConstraintSize = CGSize(width: CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT))
                    let longestWordSize = ((longestWord ?? "") as NSString).boundingRect(with: wordConstraintSize,
                                                                            options: .usesFontLeading,
                                                                            attributes: [NSFontAttributeName: proposedFont],
                                                                            context: nil)
        
                    if labelSize.height <= bounds.size.height && longestWordSize.width < constraintSize.width {
                        font = proposedFont
                        setNeedsLayout()
                        break
                    }
                }
            }
        }
        

        【讨论】:

        • 这对我有用(对于UILabel 的电子邮件列表)。我只是将分隔符从空格更改为换行符(“\n”)并删除了与height 相关的所有内容。谢谢你!
        【解决方案6】:

        改编自 @DaGaMs 的 swifty 版本。

        SWIFT 2:

        extension UILabel {
            func adjustFontSizeToFit(minimumFontSize: CGFloat, maximumFontSize: CGFloat? = nil) {
                let maxFontSize = maximumFontSize ?? font.pointSize
                for size in stride(from: maxFontSize, to: minimumFontSize, by: -CGFloat(0.1)) {
                    let proposedFont = font.fontWithSize(size)
                    let constraintSize = CGSizeMake(bounds.size.width, CGFloat(MAXFLOAT))
                    let labelSize = ((text ?? "") as NSString).boundingRectWithSize(constraintSize,
                        options: .UsesLineFragmentOrigin,
                        attributes: [NSFontAttributeName: proposedFont],
                        context: nil)
                    if labelSize.height <= bounds.size.height {
                        font = proposedFont
                        setNeedsLayout()
                        break;
                    }
                }
            }
        }
        

        SWIFT 3:

        extension UILabel {
            func adjustFontSizeToFit(minimumFontSize: CGFloat, maximumFontSize: CGFloat? = nil) {
                let maxFontSize = maximumFontSize ?? font.pointSize
                for size in stride(from: maxFontSize, to: minimumFontSize, by: -CGFloat(0.1)) {
                    let proposedFont = font.withSize(size)
                    let constraintSize = CGSize(width: bounds.size.width, height: CGFloat(MAXFLOAT))
                    let labelSize = ((text ?? "") as NSString).boundingRect(with: constraintSize,
                                                                                    options: .usesLineFragmentOrigin,
                                                                                    attributes: [NSFontAttributeName: proposedFont],
                                                                                    context: nil)
                    if labelSize.height <= bounds.size.height {
                        font = proposedFont
                        setNeedsLayout()
                        break;
                    }
                }
            }
        }
        

        【讨论】:

          【解决方案7】:

          MontiRabbit 的帖子因名声不佳无法评论,所以我会做出新的回答。他(和她的推荐人)提出的解决方案不适用于 Xcode 7.3 或更高版本,这是不精确的。 为了让它发挥作用,在故事板中,我必须:

          1. 设置宽度约束(纯宽度或尾部&前导)
          2. 设置一个高度约束(这很重要,通常使用自动调整大小不会设置标签高度)
          3. 将“Autoshrink”属性设置为“Minimum font scale”或“Minimum font size”(在这两种情况下都有效)
          4. 将“换行符”属性设置为“截断尾部”
          5. 将“Lines”属性设置为非零值

          希望对您有所帮助! ;)

          【讨论】:

          • 将换行符设置为“Truncate Tail”是违反直觉的,不应该是必要的,当您将其他所有内容都设置为您期望需要的方式时,这就是让魔法突然发生的原因.谢谢!可以确认高度约束不一定是固定高度,可以只是附加到它的容器大小或它的一部分。
          • @DuncanBabbage,不客气!所以我们可以说,标签的高度必须可以由编译器计算,以某种方式,具有高度约束或父级引用!
          【解决方案8】:

          对于 UIButton,只有这些行对我有用:

          self.centerBtn.titleLabel.numberOfLines = 2;
          self.centerBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
          self.centerBtn.titleLabel.adjustsFontSizeToFitWidth = YES;
          

          【讨论】:

            【解决方案9】:

            我已经根据上面“The Dude”的回答在 UILabel 上写了一个小类别来实现这个功能。

            https://gist.github.com/ayushn21/d87b835b2efc756e859f

            【讨论】:

            • 我必须用NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin 修改这个要点才能使其工作。
            【解决方案10】:

            我找到了这个链接http://beckyhansmeyer.com/2015/04/09/autoshrinking-text-in-a-multiline-uilabel/

            使用 Interface Builder 只需 3 个简单步骤即可解决问题:

            1. 将“自动缩小”设置为“最小字体大小”。
            2. 将字体设置为您的 最大的理想字体大小(20)并将 Lines 设置为 10,在我的情况下是 许多行将适合该字体大小的标签。
            3. 然后,更改“行 Breaks”从“Word Wrap”到“Truncate Tail”。

            希望对你有帮助!

            【讨论】:

            • 我选择 Truncate Tail 并且我的不可见线条现在可见。
            • 比自定义代码更好的解决方案。干得好。
            • 感谢您指出“Truncate Tail”,这才是与众不同的地方。
            • 将 Line Break 更改为 Truncate Tail 时反射性地摇了摇头。感谢这一点,这比任何代码解决方案都要好得多。 Xcode,IMO 中命名不佳的属性。
            • 这应该是公认的解决方案;无需编码。
            【解决方案11】:

            标记为解决方案的答案很老套且不精确。如果您正确设置以下属性,UILabel 会自动处理:

            numberOfLines 必须为非零

            adjustsFontSizeToFitWidth 必须是 YES

            lineBreakMode 必须NSLineBreakByCharWrappingNSLineBreakByWordWrapping

            【讨论】:

            • 我成功使用了:numberOfLines = 0, lineBreakMode = NSLineBreakByTruncatingTail(或 NSLineBreakByTruncatingHead 或 NSLineBreakByTruncatingMiddle)和标签的高度限制。
            • 即使在今天,这个答案的真实性也令人惊讶。如果可以的话,我可以给它100个赞!这似乎太违反直觉了,不能设置 .byWordWrapping 以使其正常工作 - 花了几个小时试图弄清楚。
            【解决方案12】:

            这是基于 itcedor 的 iOS 6 更新而更新到 iOS 7 的类别解决方案。

            头文件:

            #import <UIKit/UIKit.h>
            @interface UILabel (MultiLineAutoSize)
                - (void)adjustFontSizeToFit;
            @end
            

            以及实现文件:

            @implementation UILabel (MultiLineAutoSize)
            
            
            - (void)adjustFontSizeToFit {
                UIFont *font = self.font;
                CGSize size = self.frame.size;
            
                for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor * self.font.pointSize; maxSize -= 1.f)
                {
                    font = [font fontWithSize:maxSize];
                    CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
            
                    CGRect textRect = [self.text boundingRectWithSize:constraintSize
                                                         options:NSStringDrawingUsesLineFragmentOrigin
                                                      attributes:@{NSFontAttributeName:font}
                                                         context:nil];
            
                    CGSize labelSize = textRect.size;
            
            
                    if(labelSize.height <= size.height)
                    {
                        self.font = font;
                        [self setNeedsLayout];
                        break;
                    }
                }
                // set the font to the minimum size anyway
                self.font = font;
                [self setNeedsLayout]; }
            
            
            @end
            

            【讨论】:

            • 不需要将 minimumScaleFactor 应用到初始 pointSize 上吗? (例如,如果因子为 0.5,您将能够在此处获得非常小的字体)。
            • 像魅力一样工作,不要忘记将 UILabel 的 adjustsFontSizeToFitWidth 设置为 YES
            【解决方案13】:

            NSString-sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode: 上有一个方法,它显然自 iOS 2.0 以来就存在,但不幸的是,在没有建议的替代方案的情况下,在 iOS 7 中已弃用,因为不鼓励自动减小字体大小。我不太了解 Apple 对此的立场,因为他们在主题演讲等中使用了它,我认为如果字体大小在一个很小的范围内是可以的。这是使用此方法在 Swift 中的实现。

            var newFontSize: CGFloat = 30
                let font = UIFont.systemFontOfSize(newFontSize)
                (self.label.text as NSString).sizeWithFont(font, minFontSize: 20, actualFontSize: &newFontSize, forWidth: self.label.frame.size.width, lineBreakMode: NSLineBreakMode.ByWordWrapping)
                self.label.font = font.fontWithSize(newFontSize)
            

            我不知道有什么方法可以在不使用已弃用的方法的情况下实现这一点。

            【讨论】:

              【解决方案14】:

              这些人找到了解决方案:

              http://www.11pixel.com/blog/28/resize-multi-line-text-to-fit-uilabel-on-iphone/

              他们的解决方案如下:

              int maxDesiredFontSize = 28;
              int minFontSize = 10;
              CGFloat labelWidth = 260.0f;
              CGFloat labelRequiredHeight = 180.0f;
              //Create a string with the text we want to display.
              self.ourText = @"This is your variable-length string. Assign it any way you want!";
              
              /* This is where we define the ideal font that the Label wants to use.
                 Use the font you want to use and the largest font size you want to use. */
              UIFont *font = [UIFont fontWithName:@"Marker Felt" size:maxDesiredFontSize];
              
              int i;
              /* Time to calculate the needed font size.
                 This for loop starts at the largest font size, and decreases by two point sizes (i=i-2)
                 Until it either hits a size that will fit or hits the minimum size we want to allow (i > 10) */
              for(i = maxDesiredFontSize; i > minFontSize; i=i-2)
              {
                  // Set the new font size.
                  font = [font fontWithSize:i];
                  // You can log the size you're trying: NSLog(@"Trying size: %u", i);
              
                  /* This step is important: We make a constraint box 
                     using only the fixed WIDTH of the UILabel. The height will
                     be checked later. */ 
                  CGSize constraintSize = CGSizeMake(labelWidth, MAXFLOAT);
              
                  // This step checks how tall the label would be with the desired font.
                  CGSize labelSize = [self.ourText sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
              
                  /* Here is where you use the height requirement!
                     Set the value in the if statement to the height of your UILabel
                     If the label fits into your required height, it will break the loop
                     and use that font size. */
                  if(labelSize.height <= labelRequiredHeight)
                      break;
              }
              // You can see what size the function is using by outputting: NSLog(@"Best size is: %u", i);
              
              // Set the UILabel's font to the newly adjusted font.
              msg.font = font;
              
              // Put the text into the UILabel outlet variable.
              msg.text = self.ourText;
              

              为了让它工作,必须在界面构建器中将 IBOutlet 分配给 UILabel。

              "IBOutlet UILabel *msg;"

              所有的优点都是 11 像素的人。

              【讨论】:

                【解决方案15】:

                itedcedor 的回答有一个 pwightman 指出的问题。此外,无需修剪空格。这是修改后的版本:

                - (void)adjustFontSizeToFit {
                    UIFont *font = self.font;
                    CGSize size = self.frame.size;
                
                    for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor * self.font.pointSize; maxSize -= 1.f) {
                        font = [font fontWithSize:maxSize];
                        CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
                        CGSize labelSize = [self.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
                
                        if(labelSize.height <= size.height) {
                            self.font = font;
                            [self setNeedsLayout];
                            break;
                        }
                    }
                
                    // set the font to the minimum size anyway
                    self.font = font;
                    [self setNeedsLayout];
                }
                

                【讨论】:

                • 我面临的问题是无论你做什么,文本似乎都是左对齐的。更新:看起来取消选中“Tighten Letter Spacing”可以解决这个问题。
                【解决方案16】:

                感谢 DaGaMs 提供此解决方案。

                我已经更新如下:

                1 - 使用 iOS 6(因为 minimumFontSize 和 UILineBreakModeWordWrap 都已弃用) 2 - 从标签的文本中去除空格,因为它会导致调整大小失败(你不想知道我花了多长时间才找到那个错误)

                -(void)adjustFontSizeToFit 
                {
                    self.text = [self.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
                
                    UIFont *font = self.font;
                    CGSize size = self.frame.size;
                
                    for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor; maxSize -= 1.f)
                    {
                        font = [font fontWithSize:maxSize];
                        CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
                        CGSize labelSize = [self.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
                        if(labelSize.height <= size.height)
                        {
                            self.font = font;
                            [self setNeedsLayout];
                            break;
                        }
                    }
                    // set the font to the minimum size anyway
                    self.font = font;
                    [self setNeedsLayout];
                }
                

                【讨论】:

                • minimumScaleFactor 是一些十进制值,例如 0.2。 maxSize &gt;= self.minimumScaleFactor 然后会将大小减小到 0.2。相反,您不想要maxSize &gt;= self.minimumScaleFactor * self.font.pointSize 或类似的东西吗?
                【解决方案17】:

                我喜欢 DaGaMs 的回答,但是在使用像 UITableViewCells 这样可以返回 dequeueReusableCell: 的标签时,常规字体大小会继续缩小,即使对于一些文本较少的 tableView 单元格仍然需要原始字体大小并且可以利用原始标签的原始字体大小。

                所以,我从 DaGaM 的类别开始作为起点,我创建了一个单独的类而不是一个单独的类别,并且我确保我的故事板中的 UILabel 使用这个新类:

                #import "MultiLineAutoShrinkLabel.h"
                
                @interface MultiLineAutoShrinkLabel ()
                @property (readonly, nonatomic) UIFont* originalFont;
                @end
                
                @implementation MultiLineAutoShrinkLabel
                
                @synthesize originalFont = _originalFont;
                
                - (UIFont*)originalFont { return _originalFont ? _originalFont : (_originalFont = self.font); }
                
                - (void)quoteAutoshrinkUnquote
                {
                    UIFont* font = self.originalFont;
                    CGSize frameSize = self.frame.size;
                
                    CGFloat testFontSize = _originalFont.pointSize;
                    for (; testFontSize >= self.minimumFontSize; testFontSize -= 0.5)
                    {
                        CGSize constraintSize = CGSizeMake(frameSize.width, MAXFLOAT);
                        CGSize testFrameSize = [self.text sizeWithFont:(font = [font fontWithSize:testFontSize])
                                                     constrainedToSize:constraintSize
                                                         lineBreakMode:self.lineBreakMode];
                        // the ratio of testFontSize to original font-size sort of accounts for number of lines
                        if (testFrameSize.height <= frameSize.height * (testFontSize/_originalFont.pointSize))
                            break;
                    }
                
                    self.font = font;
                    [self setNeedsLayout];
                }
                
                @end
                

                【讨论】:

                • +1 用于处理 UITableViewCells。但是你的接口 MultilineAutoShrinkLabel.h 的代码在哪里?
                • @Rhubarb,这只是微不足道的:具有一个功能的 UILabel 的子类,- (void)quoteAutoshrinkUnquote; ......实际上,我已经开始使用类似但更复杂的东西来处理上的附件视图右侧以及它可以是 2 种不同尺寸的事实,允许每个单元或多或少的屏幕空间。
                • 我用这个答案回答了我自己的问题,还更新了代码以删除不推荐使用的方法stackoverflow.com/a/30898604/758083
                猜你喜欢
                • 2014-10-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-08-01
                相关资源
                最近更新 更多