Swift:编程创建固定宽度的UILabel,根据文本长度自动调整垂直大小

13

我看到了关于垂直调整大小的答案,其中涉及到自动布局,但我创建的UILabel只在运行时需要。(我可能需要零个或多个这些标签。)

示例 (忽略颜色):

  1. 短文本(注意与更长文本相同的宽度):

enter image description here

  1. 较长的文本(注意与较短文本相同的宽度示例,用于添加更多文本的多行):

enter image description here

如果文本可以适合固定宽度的一行,则标签不需要垂直调整大小。但是如果有更多字符,则标签应该保持垂直扩展以适应这些额外字符。文本应该一行接着一行地换行。文本应该从标签的左上角开始。

更具体地说:

let marker = GMSMarker(position: myLatLng)
// see https://dev59.com/V1kS5IYBdhLWcg3wNkH6#40211383 for imageWithView
marker.icon = imageWithView(label) // **how do i create this label?**
marker.map = map // map is a GMSMapView

这些标签可以出现在屏幕的任何位置。这是一个地图应用程序,每个标签将被放置在随机位置。标签的位置彼此之间没有关联。


可能是根据文本调整UILabel高度的重复问题。 - alexburtnik
@alexburtnik,你能否重新考虑一下这个问题不是重复的吗?那个解决方案似乎在这里不起作用。请注意固定宽度的附加要求。也许你有一些想法,为什么下面的解决方案不起作用。 - lf215
我已撤销了关闭投票,但它仍然是重复的。以下解决方案假定您正在使用自动布局约束。我的解决方案是另一种选择,它是手动更新框架。 - alexburtnik
2个回答

16

UIView有两个有用的方法:sizeToFit()sizeThatFits(_:)

第一个方法将视图调整为适合子视图内容的最小大小,而第二个方法不改变框架大小,但返回计算出的大小:(1) 适合所有子视图和(2) 不超过参数size

所以你可以使用sizeThatFits来达到你的目的:

let label = UILabel()

override func viewDidLoad() {
    super.viewDidLoad()

    label.backgroundColor = UIColor.orange
    label.textColor = UIColor.white
//  label.text = "ultimate Frisbee"
    label.text = "ultimate Frisbee\nin 3 minutes,\nall welcome|2"
    label.numberOfLines = 10
    view.addSubview(label)

    updateLabelFrame()
}

func updateLabelFrame() {
    let maxSize = CGSize(width: 150, height: 300)
    let size = label.sizeThatFits(maxSize)
    label.frame = CGRect(origin: CGPoint(x: 100, y: 100), size: size)
}

输出:

在此输入图像描述 在此输入图像描述

附言:你也可以使用自动布局约束来解决问题,但我不是很喜欢在编程中使用它们。


5
将标签的numberOfLines属性设置为零,并使用约束(通过显式约束宽度或约束前导和尾随边缘到其他视图,例如标签的父视图)来固定标签的宽度。然后标签将自动垂直调整大小以适应文本高度。您需要通过其顶部约束将一个标签固定,以便视图系统知道从哪里开始布局,然后所有其他标签的顶部应该受限于前一个标签的底部。这样他们都会相对于前一个标签的高度进行布局。
针对您的评论做出的修改:
您可以在iOS 9及更高版本中使用widthAnchor属性来显式地设置视图的宽度。您可以使用NSLayoutConstraints(搜索SO获取示例)在旧版iOS上设置它。
例如: label.widthAnchor.constraintEqualToConstant(50.0).active = true 这将将标签的宽度设置为50个点,但不会固定其高度,因此如果使用numberOfLines = 0,则标签将在设置文本时自动垂直调整大小。

我的标签位置彼此之间没有关联。 - lf215
@lf215,你只需要将numberOfLines属性设置为零即可获得动态高度(假设宽度是固定/受限的,否则它将布局为一行长线)。 - par
1
@lf215 是的,完全正确,或者使用 widthAnchor,请参见我的答案编辑。 - par
我尝试了你的代码:let label = UILabel() 然后是 label.widthAnchor.constraintEqualToConstant(50.0).active = true;。它说无法满足约束条件。当我尝试将其简单地添加为子视图以进行测试时,就会出现这种情况。(当我尝试使用此处的方法时,我得到了一个可能相关的不同错误。)我错过了什么? - lf215
2
你可能想要设置 label.translatesAutoresizingMaskIntoConstraints = false - rob mayoff
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接