将 UILabel 高度调整为文本

Posted

技术标签:

【中文标题】将 UILabel 高度调整为文本【英文标题】:Adjust UILabel height to text 【发布时间】:2014-09-30 13:44:27 【问题描述】:

我有一些标签,我想根据文本调整它们的高度,这是我现在为此编写的代码

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat
    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.ByWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height

编辑:

问题不在这段代码中,所以我的修复是在问题本身。它可能对其他人仍然有用!

【问题讨论】:

看看 NSString UIKit 添加的内容,那里有一些方法可以根据需要计算大小,而无需创建 UILabel。 @VladimirGritsenko 'sizeWithFont' 方法在 Swift 中不可用:( 我承认我不是 Swift 专家,但我相信您可以添加自己的桥接方法。仍然值得创建 UILabel 来计算大小。 @TheBurgerShot sizeWithFont 可能不适用于 Swift String 但它可以在 NSString 上使用,您应该仍然可以调用它。 最后,错误是不同的,与此方法无关。虽然这可能对其他人仍然有帮助。 【参考方案1】:

我刚刚把它放在操场上,它对我有用。

为 Swift 4.0 更新

import UIKit

 func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat
    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height


let font = UIFont(name: "Helvetica", size: 20.0)

var height = heightForView("This is just a load of text", font: font, width: 100.0)

斯威夫特 3:

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()

    return label.frame.height

【讨论】:

这在操场上也适用于 mee,错误似乎不会发生在这个特定的地方,当我删除这种方法的用法时,它会抱怨一些 println 或只是一行cmets(然后它也显示 EXC_BAD_ACCESS code=2) 它在操场上工作,但在 XCode 6.1 中的视图控制器内部没有按需要进行大小调整 我有点犹豫是否要根据尺寸创建一个新的UILabel;如果在 layoutSubviews 内部使用此方法,并且在每个完整布局中可能会被多次调用,则额外的对象创建可能会引入明显的延迟,尤其是在滚动期间。 让 textRect = textString.boundingRectWithSize(CGSizeMake(320, 2000),选项:.UsesLineFragmentOrigin,属性:textAttributes,上下文:nil) 我无法在我的视图控制器中调用这个函数...你能告诉我可能的原因吗?【参考方案2】:

我有强大的工作解决方案。

在布局子视图中:

title.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 0)
title.sizeToFit()
title.frame.size = title.bounds.size

在文本设置器中:

title.text = newValue
setNeedsLayout()

UPD。 当然有这个 UILabel 设置:

title.lineBreakMode = .byWordWrapping
title.numberOfLines = 0

【讨论】:

证明..谢谢!【参考方案3】:

只需设置:

label.numberOfLines = 0

标签会根据输入的文本量自动调整其高度。

【讨论】:

这不会使 UILabel 调整它的高度。【参考方案4】:

如果你愿意,我会创建这个扩展

extension UILabel 
    func setSizeFont (sizeFont: CGFloat) 
        self.font =  UIFont(name: self.font.fontName, size: sizeFont)!
        self.sizeToFit()
    

【讨论】:

【参考方案5】:

Anorak 建议的解决方案作为 UILabel 扩展中的计算属性:

extension UILabel

var optimalHeight : CGFloat
    
        get
        
            let label = UILabel(frame: CGRectMake(0, 0, self.frame.width, CGFloat.max))
            label.numberOfLines = 0
            label.lineBreakMode = self.lineBreakMode
            label.font = self.font
            label.text = self.text

            label.sizeToFit()

            return label.frame.height
         
    

用法:

self.brandModelLabel.frame.size.height = self.brandModelLabel.optimalHeight

【讨论】:

无法分配给属性:'height' 是一个 get-only 属性。【参考方案6】:

这是在 Swift 中计算文本高度的方法。然后可以从rect中获取高度,设置label或者textView等的约束高度。

let font = UIFont(name: "HelveticaNeue", size: 25)!
let text = "This is some really long text just to test how it works for calculating heights in swift of string sizes. What if I add a couple lines of text?"

let textString = text as NSString

let textAttributes = [NSFontAttributeName: font]

let textRect = textString.boundingRectWithSize(CGSizeMake(320, 2000), options: .UsesLineFragmentOrigin, attributes: textAttributes, context: nil)

【讨论】:

【参考方案7】:

在@Anorak 回答之后,我将此扩展名添加到 String 并发送了一个 inset 作为参数,因为很多时候您需要对文本进行填充。 无论如何,也许有些人会觉得这很有用。

extension String 

    func heightForWithFont(font: UIFont, width: CGFloat, insets: UIEdgeInsets) -> CGFloat 

        let label:UILabel = UILabel(frame: CGRectMake(0, 0, width + insets.left + insets.right, CGFloat.max))
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.ByWordWrapping
        label.font = font
        label.text = self

        label.sizeToFit()
        return label.frame.height + insets.top + insets.bottom
    

【讨论】:

label.lineBreakMode = NSLineBreakMode.ByWordWrapping 这行对我有帮助,谢谢。【参考方案8】:

在需要动态标签高度的地方调用这个方法

func getHeightforController(view: AnyObject) -> CGFloat 
    let tempView: UILabel = view as! UILabel
    var context: NSStringDrawingContext = NSStringDrawingContext()
    context.minimumScaleFactor = 0.8

    var width: CGFloat = tempView.frame.size.width

    width = ((UIScreen.mainScreen().bounds.width)/320)*width

    let size: CGSize = tempView.text!.boundingRectWithSize(CGSizeMake(width, 2000), options:NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: tempView.font], context: context).size as CGSize

    return size.height

【讨论】:

【参考方案9】:

如果您使用 AutoLayout,您只能通过配置 UI 调整 UILabel 高度。

适用于 iOS8 或更高版本

为您的UILabel 设置约束前导/尾随 并将UILabel的行从1改为0

适用于 iOS7

首先,你需要为UILabel添加包含高度 然后,将Relation从Equal修改为Greater than or Equal

最后,将UILabel的行从1改为0

您的UILabel 会根据文字自动增加高度

【讨论】:

如果标签在单元格内。何时以及如何相应地增加单元格高度? @oyalhi,如果您的标签在 tableview 单元格内,请参阅我的另一篇帖子 ***.com/a/36277840/5381331 这对我来说非常有效!设置约束,它将正常工作! 不适合我...UILabel 中的“标签”一词使高度=20。此设置后仍为 20。 不知道“添加包含 UILabel 的高度”是什么意思,并且 UIBuilder 中没有第一项(如图)的“高度约束”部分??【参考方案10】:

基于 Anorak 的回答,我也同意 Zorayr 的担忧,所以我添加了几行来删除 UILabel 并只返回 CGFloat,我不知道它是否有帮助,因为原始代码没有添加 UIabel ,但它不会抛出错误,所以我使用下面的代码:

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat

    var currHeight:CGFloat!

    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.ByWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()

    currHeight = label.frame.height
    label.removeFromSuperview()

    return currHeight

【讨论】:

【参考方案11】:

Swift 4.0

self.messageLabel = UILabel(frame: CGRect(x: 70, y: 60, width:UIScreen.main.bounds.width - 80, height: 30)

messageLabel.text = message

messageLabel.lineBreakMode = .byWordWrapping //in versions below swift 3 (messageLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping)    
messageLabel.numberOfLines = 0 //To write any number of lines within a label scope

messageLabel.textAlignment = .center

messageLabel.textColor = UIColor.white

messageLabel.font = messageLabel.font.withSize(12)

messageLabel.sizeToFit()

Blockquote NSParagraphStyle.LineBreakMode,适用于整个段落,而不是段落中的单词。此属性在正常绘图期间以及必须减小字体大小以适合其边界框中的标签文本的情况下均有效。该属性默认设置为 byTruncatingTail。

This link describes the storyboard way of doing the same

【讨论】:

纯代码答案不被认为是好的做法。请考虑添加一些关于您的答案如何解决问题的解释。【参考方案12】:

Swift 4.0

我不计算文本/标签高度,而是在插入(动态)文本后调整标签大小。

假设 myLabel 是有问题的 UILabel:

let myLabel = UILabel(frame: CGRect(x: 0, y: 0, width: *somewidth*, height: *placeholder, e.g. 20*))
myLabel.numberOfLines = 0
myLabel.lineBreakMode = .byWordWrapping
...

现在有趣的部分来了:

var myLabelText: String = "" 
   didSet 
      myLabel.text = myLabelText
      myLabel.sizeToFit()
   

【讨论】:

【参考方案13】:

Swift 4.1扩展方法计算标签高度:

extension UILabel 

    func heightForLabel(text:String, font:UIFont, width:CGFloat) -> CGFloat 
        let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.byWordWrapping
        label.font = font
        label.text = text

        label.sizeToFit()
        return label.frame.height
    


【讨论】:

【参考方案14】:

在 swift 4.1 和 Xcode 9.4.1 中

只有 3 个步骤

第 1 步)

//To calculate height for label based on text size and width
func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat 
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height

第 2 步)

//Call this function
let height = heightForView(text: "This is your text", font: UIFont.systemFont(ofSize: 17), width: 300)
print(height)//Output : 41.0

第 3 步)

//This is your label
let proNameLbl = UILabel(frame: CGRect(x: 0, y: 20, width: 300, height: height))
proNameLbl.text = "This is your text"
proNameLbl.font = UIFont.systemFont(ofSize: 17)
proNameLbl.numberOfLines = 0
proNameLbl.lineBreakMode = .byWordWrapping
infoView.addSubview(proNameLbl)

【讨论】:

【参考方案15】:

要在 swift 中使标签动态化,不要给出高度约束,并且在情节提要中使标签行数 0 也给出底部约束,这是我根据内容大小处理动态标签的最佳方式。

【讨论】:

【参考方案16】:

Swift 5,XCode 11 故事板方式。我认为这适用于 ios 9 及更高版本。例如,您希望“描述”标签获取动态高度,请按照以下步骤操作:

1) 选择描述标签 -> 转到属性检查器(铅笔图标),设置: 行数:0 换行:自动换行

2) 从情节提要中选择您的 UILabel 并转到 Size Inspector(标尺图标), 3) 对于与您的标签交互的所有其他 UIView(标签、按钮、图像视图等)组件,转到“内容压缩阻力优先级为 1”。

例如,我的视图中有 UIImageView、标题标签和描述标签。我将内容压缩阻力优先级设置为 UIImageView,将标题标签设置为 1,将描述标签设置为 750。这将使描述标签具有所需的高度。

【讨论】:

【参考方案17】:

你也可以使用sizeThatFits函数。

例如:

label.sizeThatFits(superView.frame.size).height

【讨论】:

以上是关于将 UILabel 高度调整为文本的主要内容,如果未能解决你的问题,请参考以下文章

UILabel 不调整高度以适合文本

Swift - UILabel 自动调整为文本长度

根据文本调整 UILabel 高度

UILabel 动画调整大小副作用

根据 Swift 中的 UILabel 文本调整 UIView 高度

AutoLayout 将 UILabel 高度设置为零