【问题标题】:Dynamically adjust UILabel frame height after dynamically adjusting the internal text size to fit动态调整内部文字大小以适应后动态调整UILabel框架高度
【发布时间】:2020-01-02 06:46:31
【问题描述】:

我正在使用一个 UILabel,该 UILabel 被限制为固定宽度,并且不超过某个高度(例如,固定为屏幕大小的一半)

为了让我们的应用能够跨 iOS 设备运行,我在 UILabel 上将 adjustsfontsizetofitwidth 设置为 true。如果屏幕尺寸很小,这会导致文本字体大小的调整。

但是,如果实际调整了字体大小,UILabel 现在似乎对文本有额外的顶部和底部填充。这被标记为其内在内容大小的一部分。

这个额外的垂直填充是有问题的,因为我有一个按钮需要位于最后一行文本基线的正下方。

我现在需要一种方法来重新调整我的框架以紧密适应新调整的文本大小。

我尝试在 layoutSubviews() 中使用 sizeToFit()invalidateIntrinsicContentSize 作为我的视图类,但无济于事。

它似乎类似于thisthis,它们都没有适合我的答案。

class ProblemExample: UIViewController {
     private let instructionsLabel: UILabel = {
            let label = UILabel().disableAutoresizingMask()
            label.numberOfLines = 0
            label.text = "Lorem ipsum dolor sit amet, ut adhuc argumentum vix, vix eruditi appetere corrumpit in. Quod cibo mnesarchum ex sea. Ad qui case assum delicata, ei laudem prodesset democritum per, alia admodum efficiantur has id. Semper integre ei est, quo dolor causae definitionem ei. Malis impedit vim at, vero quas sit ea. Quaeque expetenda an est."
            label.font = Theme.headingFont // BIG FONT
            label.setLineSpacing(multiple: 1.15)
            label.textColor = .black
            label.lineBreakMode = .byTruncatingTail
            label.adjustsFontSizeToFitWidth = true;
            label.minimumScaleFactor = 0.5

            return label
        }()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.addSubview(instructionsLabel)
        // Using https://github.com/roberthein/TinyConstraints for syntactical lightness
        instructionsLabel.widthToSuperview(multiplier:0.5)
        instructionsLabel.heightToSuperview(multiplier:0.5, relation:.equalOrLess)
        instructionsLabel.centerYToSuperview()

        button = UIButton()
        self.addSubView()
        button.bottom(to: instructionsLabel)
    }
}

【问题讨论】:

  • 如果您需要动态高度,则不要使用此约束 heightToSuperview ..... 只需使用 left、right、bottom、top 约束,您可以使用宽度约束但不能使用高度。
  • @Winston try "label.lineBreakMode = .wordWrap" 然后它会增加高度。考虑到您已经给出了所有适当的约束(顶部、领先、训练、底部)并记住顶部和底部约束不是固定值。
  • 我计算UILabel高度的方法,stackoverflow.com/a/45182097/419348
  • @AbuUlHassan 我的意思是 heightToSuperview 小于或等于约束。

标签: ios swift uilabel


【解决方案1】:

当您需要将文本放入框架或根据文本大小拉伸框架时,您可以从内置行为中受益。在我看来,你需要两者。因此,您必须自己做。

大概的流程如下:

  • 获取要分配给标签的文本
  • 在知道文本宽度的情况下计算文本的高度 (see this)
  • 如果文字高度大于最大标签高度,则将标签设置为最大高度,否则将其设置为文字高度
  • 将文本分配给标签

【讨论】:

  • 感谢您解决我最初的问题。我仍然无法理解此行为的实现:如果通过自动布局计算宽度,我将在哪个阶段知道宽度?
  • 在调用viewDidLayoutSubviews() 之后,您可以计算宽度(例如,superview.width - label.leading - label.trailing,或任何您的公式)。
  • 所以你的意思是在覆盖viewDidLayoutSubviews()的定义中?
  • 您可以在 viewDidLayoutSubviews() 中或在它被调用后的任何时间执行这些步骤。你也需要有文字,不是吗? (我不知道它是来自后端还是其他地方......)
  • 手动输入计算宽度的公式似乎很奇怪,而我应该从自动布局中获取它。为了澄清,我尝试了你的解决方案,但即使在viewDidLayoutSubviews() 时,我仍然没有真正的宽度。我不明白adjustsFontSizeToFitWidth 属性如何在引擎盖下进行重新缩放。如果我有那个代码,我应该能够解决这个问题。
【解决方案2】:

尝试使用以下代码,始终在viewDidLayoutSubViewsviewDidLayoutSubViews 之后添加运行时渲染

 override func viewDidLoad() {
        super.viewDidLoad()

    }

 override func viewDidLayoutSubViews(){
        super.viewDidLayoutSubViews()
        self.addSubview(instructionsLabel)
        // Using https://github.com/roberthein/TinyConstraints for syntactical lightness
        instructionsLabel.widthToSuperview(multiplier:0.5)
        instructionsLabel.heightToSuperview(multiplier:0.5, relation:.equalOrLess)
        instructionsLabel.centerYToSuperview()
        if button == nil {
            button = UIButton()
            self.addSubView()
            button.bottom(to: instructionsLabel)
        }
}

【讨论】:

  • 这太过分了。只有一层额外的依赖表达式。如果对动态约束做动态约束呢?
  • 为了处理这个问题,我们使用 nil 来处理它,在第一次初始化之后,它不会进入 if 条件。对于标签,它已经很懒了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-14
  • 2012-08-07
  • 2013-06-04
  • 1970-01-01
  • 2010-11-03
相关资源
最近更新 更多