简体   繁体   English

Swift - 调整 fontSize 以适应布局的宽度(以编程方式)

[英]Swift - Adjusting fontSize to fit the width of the layout (programmatically)

I've been looking for something to dynamically adjust my fontSize to fit the width of my layout box.我一直在寻找一些东西来动态调整我的fontSize以适应我的布局框的宽度。 But all the answers I can find, is either to use this:但我能找到的所有答案都是使用这个:

label.adjustsFontSizeToFitWidth = true

Which does work.哪个有效。 But only if I don't have setTranslatesAutoresizingMaskIntoConstraints set to false .setTranslatesAutoresizingMaskIntoConstraints是我没有将setTranslatesAutoresizingMaskIntoConstraints设置为false

Please note that I don't use storyboards.请注意,我不使用故事板。 So to have full control over my other constraints I need this line:所以要完全控制我的其他约束,我需要这一行:

label.setTranslatesAutoresizingMaskIntoConstraints(false)

So how can I adjust the font size to fit the width without using storyboard and when I can't use adjustsFontSizeToFitWidth .那么如何在不使用故事板的情况下调整字体大小以适应宽度以及何时无法使用adjustsFontSizeToFitWidth

After I figure out how to adjust the font size to fit the width.在我弄清楚如何调整字体大小以适应宽度之后。 I also need to adjust the height of the layout box to fit the font size.我还需要调整布局框的高度以适应字体大小。 There seems to be documentation on that though, but if you happen to know the answer of this as well, it would be greatly appreciated.虽然似乎有关于此的文档,但如果您碰巧也知道这个答案,将不胜感激。

Thanks in advance提前致谢

Try the following commands for your label:为您的标签尝试以下命令:

label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.2

And try to change the lines of the label to 0 and 1 (check both cases):并尝试将标签的行更改为 0 和 1(检查两种情况):

label.numberOfLines = 0 // or 1

MinimumScaleFactor range is 0 to 1. So we are setting the MinimumScaleFactor with respect to our font size as follows MinimumScaleFactor范围是 0 到 1。所以我们将根据字体大小设置MinimumScaleFactor ,如下所示

Objective C目标 C

[lb setMinimumScaleFactor:10.0/[UIFont labelFontSize]];
lb.adjustsFontSizeToFitWidth = YES;

Swift 3.0斯威夫特 3.0

lb.minimumScaleFactor = 10/UIFont.labelFontSize
lb.adjustsFontSizeToFitWidth = true

I don't know if this will completely answer your question, but you can use this extension to calculate your own font sizes to fit.我不知道这是否能完全回答你的问题,但你可以使用这个扩展来计算你自己的字体大小。

Swift 3斯威夫特 3

extension String {
   func height(constrainedBy width: CGFloat, with font: UIFont) -> CGFloat {
       let constraintSize = CGSize(width: width, height: .max)
       let boundingBox = self.boundingRectWithSize(constraintSize, options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

       return boundingBox.height
   }

   func width(constrainedBy height: CGFloat, with font: UIFont) -> CGFloat {
       let constrainedSize = CGSize(width: .max, height: height)
       let boundingBox = self.boundingRectWithSize(constrainedSize, options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

       return boundingBox.width
   }
}

Update - Adds example and updates code to Swift 5更新 - 向 Swift 5 添加示例和更新代码

Swift 5斯威夫特 5

extension String {
    func height(constrainedBy width: CGFloat, with font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)

        return boundingBox.height
    }

    func width(constrainedBy height: CGFloat, with font: UIFont) -> CGFloat {
        let constrainedRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constrainedRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)

        return boundingBox.width
    }
}

Here is my logic to make sure that two different labels had the same font size.这是我确保两个不同标签具有相同字体大小的逻辑。 In my case it was two labels for the user's first and last name.就我而言,它是用户名字和姓氏的两个标签。 The reason I needed two labels for this, is because each label is independently animated.我为此需要两个标签的原因是每个标签都是独立动画的。

class ViewController: UIViewController {
      ...

      func viewDidLoad() {
         super.viewDidLoad()
         fixFontSizes()
         ...
      }

      func fixFontSizes() {
         let leadingMargin = self.leadingContainerConstraint.constant
         let trailingMargin = self.trailingContainerConstraint.constant
         let maxLabelWidth = self.view.bounds.width - leadingMargin - trailingMargin

         let firstName = self.firstNameLabel.text ?? ""
         let lastName = self.lastNameLabel.text ?? ""

         let firstNameWidth = firstName.width(constrainedBy: self.container.bounds.height, with: self.firstNameLabel.font)
         let lastNameWidth = lastName.width(constrainedBy: self.container.bounds.height, with: self.lastNameLabel.font)

         let largestLabelWidth = max(firstNameWidth, lastNameWidth)
         guard largestLabelWidth > maxLabelWidth else { return }

         let largestTextSize = max(self.firstNameLabel.font.pointSize, self.lastNameLabel.font.pointSize)

         let labelToScreenWidthRatio = largestLabelWidth / maxLabelWidth
         let calculatedMaxTextSize = floor(largestTextSize / labelToScreenWidthRatio)

         self.firstNameLabel.font = self.firstNameLabel.font.withSize(calculatedMaxTextSize)
         self.lastNameLabel.font = self.lastNameLabel.font.withSize(calculatedMaxTextSize)
      }


}

I just did that you needed , Works perfectly !我只是做了你需要的,完美的作品! (Programmatically ONLY) - We are setting large font size to the label , in order to re-scale it to the perfect font size. (仅以编程方式) - 我们正在为 label 设置大字体大小,以便将其重新缩放到完美的字体大小。

self.label.font = UIFont(name: "Heiti TC", size: 60)
self.label.numberOfLines = 0
self.label.minimumScaleFactor = 0.1
self.label.baselineAdjustment = .alignCenters
self.label.textAlignment  = .center

If you are using AutoLayout, implement this code in viewDidLayoutSubviews (after the layout has been laid out).如果您使用 AutoLayout,请在viewDidLayoutSubviews实现此代码(在布局布局之后)。

Yours, Roi你的,罗伊

Swift 4 conversion of above: Swift 4 以上的转换:

extension String
{
    func height(constrainedBy width: CGFloat, with font: UIFont) -> CGFloat
    {
        let constraintSize = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)

        return boundingBox.height
    }

    func width(constrainedBy height: CGFloat, with font: UIFont) -> CGFloat
    {
        let constrainedSize = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constrainedSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)

        return boundingBox.width
    }
}

Swift 5斯威夫特 5

extension String
{
    func height(constrainedBy width: CGFloat, with font: UIFont) -> CGFloat
    {
        let constraintSize = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)

        return boundingBox.height
    }

    func width(constrainedBy height: CGFloat, with font: UIFont) -> CGFloat
    {
        let constrainedSize = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constrainedSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)

        return boundingBox.width
    }
}

Here's a hack solution:这是一个黑客解决方案:

var size: CGFloat = 20

    while titleLabel.frame.width > containerView.frame.width {

        titleLabel.font = UIFont.systemFont(ofSize: size)
        titleLabel.sizeToFit()
        size -= 1

    }

I had a similar problem using a UILabel inside a UITableViewCell and my cell's were adjusting their heights dynamically as well (refer to this if you wanna know more about dynamic cell heights: https://www.raywenderlich.com/129059/self-sizing-table-view-cells ) 我在UITableViewCell中使用UILabel时遇到了类似的问题,我的单元格也在动态调整其高度(如果你想了解更多有关动态单元格高度的信息,请参阅此内容: https//www.raywenderlich.com/129059/self-sizing -table-view-cells

And no matter what I did for the mimimum font scale, it wasn't working. 无论我为最小字体量表做了什么,它都无法正常工作。 Turns out, for this feature to work you also have to set the Line Break property to Truncate Tail or Middle or Head. 事实证明,要使此功能起作用,您还必须将Line Break属性设置为Truncate Tail或Middle或Head。 If you have Word Wrap or Character Wrap it won't dynamically scale down your UILabel font (I had a custom font created called: Title 2). 如果你有Word Wrap或Character Wrap,它将不会动态缩小你的UILabel字体(我有一个名为Title 2的自定义字体)。

Hope this helps someone else trying to figure this out. 希望这有助于其他人试图解决这个问题。

Here is a screenshot of my UILabel properties: 这是我的UILabel属性的屏幕截图:

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何以编程方式设置字体大小以适应 swift4 中的 numberOflines 值 - How to set the fontsize programmatically to fit numberOflines value in swift4 将按钮的字体大小设置为最大以适合宽度和高度 - Set fontsize of button to maximum to fit in width and height 如何在UIButton中调整文本的字体大小以在Swift中以编程方式适应宽度? - How to adjust font size of text in a UIButton to fit the width programmatically in Swift? 在Swift中调整UIWebview的高度/宽度 - Adjusting height/width of UIWebview in Swift iOS Swift UITextfield 调整字体大小宽度 - iOS Swift UITextfield adjust fontsize width 如何通过自动布局以编程方式快速设置旋转时UICollectionView的宽度 - How to set width of UICollectionView on rotation with auto layout programmatically swift 如何在ios swift中以编程方式创建自动布局等宽约束? - How to create Auto layout equal width constraint programmatically in ios swift? 宽度和高度无法通过Xcode自动布局进行调整 - Width and height not adjusting with Xcode Auto Layout 在 UITableViewController (Swift - Xcode) 中调整按钮宽度 - Adjusting button width in UITableViewController (Swift - Xcode) Swift以编程方式创建宽度百分比 - Swift make percentage of width programmatically
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM