如何通过仅改变高度而不是宽度来改变UFabel的大小?

时间:2012-10-25 11:44:17

标签: objective-c uilabel xcode4.5

[self.Review sizeToFit];

sizeToFit之前的结果:

NSStringFromCGRect(self.Review.frame): {{90, 20}, {198, 63}}

sizeToFit后的结果:

NSStringFromCGRect(self.Review.frame): {{90, 20}, {181, 45}}

我希望宽度保持不变。我只是想改变身高。自动遮罩是

(lldb) po self.Review
(UILabel *) $1 = 0x08bb0fe0 <UILabel: 0x8bb0fe0; frame = (90 20; 181 45); text = 'I'm at Mal Taman Anggrek ...'; clipsToBounds = YES; opaque = NO; autoresize = LM+RM+H; userInteractionEnabled = NO; layer = <CALayer: 0x8bb68b0>>

我知道有办法这样做: How to adjust and make the width of a UILabel to fit the text size?

答案要么很奇怪(我们需要重新补充字体信息)。或者不清楚。

  

您还需要定义最大宽度,然后告诉您的程序   如果sizeToFit为您提供的宽度大于该最大值,该怎么办。

我将使用使用sizeWithFont的奇怪解决方案。这很奇怪,因为UILabel已经知道标签中的字体了。

实际上sizeToFit究竟是如何表现的?它如何决定我们是否需要更薄或更高的UILabel?

10 个答案:

答案 0 :(得分:40)

这就是它的完成方式。因为标签已经包含了字体信息,所以在这种方法中包含它很简单。

CGSize size = [label.text sizeWithFont:label.font
                     constrainedToSize:CGSizeMake(maxWidth, MAXFLOAT)
                         lineBreakMode:UILineBreakModeWordWrap]; 
CGRect labelFrame = label.frame;
labelFrame.size.height = size.height;
label.frame = labelFrame;

使用更新boundingRectWithSize

的Swift版本
let maxHeight = CGFloat.infinity
let rect = label.attributedText?.boundingRectWithSize(CGSizeMake(maxWidth, maxHeight), 
       options: .UsesLineFragmentOrigin, context: nil)
var frame = label.frame
frame.size.height = rect.size.height
label.frame = frame

答案 1 :(得分:40)

您可以使用sizeThatFits获得相同的结果。

CGSize size = [label sizeThatFits:CGSizeMake(label.frame.size.width, CGFLOAT_MAX)];
CGRect frame = label.frame;
frame.size.height = size.height;
label.frame = frame;

或者,使用sizeToFit。

CGRect frame = label.frame;
[label sizeToFit];
frame.size.height = label.frame.size.height;
label.frame = frame;

答案 2 :(得分:17)

sizeToFit效果很好。唯一的问题是它基于控件的当前大小。

例如,如果要使用标签回收表格视图单元格,则标签在前一个单元格中的宽度可能会减小,因此,对sizeToFit的调用可能看起来不可靠。

在发送sizeToFit消息之前,只需重置控件的原始宽度。

答案 3 :(得分:2)

我认为你不应该使用NSString的{​​{1}}方法,size...已经有了一个API,就像@vatrif指出的那样(内部可能只使用{{1}方法)。

尽管如此我认为UILabel的API可以改进。这就是为什么我认为一个类别将是最优雅的解决方案:

NSString

只有一件事:我不确定该方法的适当名称:

  • sizeToFitHeight?
  • heightToFit?

非常感谢评论,谢谢!

答案 4 :(得分:2)

2017年答案......

c = CGSize(宽度:yourWidth,身高:CGFloat.greatestFiniteMagnitude)
result = sizeThatFits(c).height

因此...

let t = .... your UITextView
let w = .... your known width of the item

let trueHeight = t.sizeThatFits(
                   CGSize(width: t, height: CGFloat.greatestFiniteMagnitude)).height

那就是它。

很多时候,你想知道高度 差异与&#34;普通&#34;单行录入

如果您正在制作某种与UTableView无关的单元格(例如,某种自定义堆栈视图),则会出现这种情况。您必须在某个时刻手动设置高度。在你的故事板上,根据你的意愿构建它,使用任何短字符串的示例文本(例如,&#34; A&#34;),当然在任何正常情况下只有一行。然后你做这样的事......

func setTextWithSizeCorrection() { // an affaire iOS

    let t = .... your UITextView
    let w = .... your known width of the item

    let oneLineExample = "A"
    let actualText = yourDataSource[row].description.whatever

    // get the height as if with only one line...

    experimental.text = oneLineExample
    let oneLineHeight = t.sizeThatFits(
               CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)).height

    // get the height with the actual long text...
    // (note that usually, you do not want a one-line minimum)

    experimental.text = (actualText == "") ? oneLineExample : actualText
    let neededHeight = t.sizeThatFits(
              CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)).height

    experimental.text = actualText

    let delta = neededHeight - oneLineHeight

    set the height of your cell, or whatever it is(standardHeight + delta)
}

最后一点:iOS中真正愚蠢的事情之一就是UITextView里面有一个奇怪的边缘。这意味着您无法在UITextViews和标签之间进行交换;它会导致许多其他问题。 Apple还没有解决这个问题。解决问题很困难:以下方法通常都可以:

@IBDesignable class UITextViewFixed: UITextView {
    override func layoutSubviews() {
        super.layoutSubviews()
        setup()
    }
    func setup() {
        textContainerInset = UIEdgeInsets.zero;
        textContainer.lineFragmentPadding = 0;
    }
}

来自Apple的破坏,无法使用的UITextView ......

enter image description here

在大多数情况下,

UITextViewFixed是可接受的修复:

enter image description here

(为了清楚起见,添加了黄色。)

答案 5 :(得分:1)

同意API将从此添加中受益。让您的生活更轻松,并在Swift中为UILabel类添加扩展,如下所示:

extension UILabel {

    func sizeToFitHeight() {
        let size:CGSize = self.sizeThatFits(CGSizeMake(self.frame.size.width, CGFloat.max))
        var frame:CGRect = self.frame
        frame.size.height = size.height
        self.frame = frame
    }
}

答案 6 :(得分:1)

SWIFT 3的固定解决方案

CGFloat.greatestFiniteMagnitude用于maxHeight。

let size = CGSize.init(width: yourLabel.frame.size.width,
                       height: CGFloat.greatestFiniteMagnitude)
let rect = errorLabel.attributedText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil)
var frame = errorLabel.frame
frame.size.height = (rect?.size.height)!
errorLabel.frame = frame


或创建UIlabel扩展名,并调用方法yourLabel. sizeToFitHeight()

extension UILabel {

    func sizeToFitHeight() {
        let maxHeight : CGFloat = CGFloat.greatestFiniteMagnitude
        let size = CGSize.init(width: self.frame.size.width, height: maxHeight)
        let rect = self.attributedText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil)
        var frame = self.frame
        frame.size.height = (rect?.size.height)!
        self.frame = frame
    }

} 

答案 7 :(得分:1)

Swift 3的这个问题的简单扩展。

extension UILabel {
    func sizeToFitHeight() {
        let size: CGSize = self.sizeThatFits(CGSize.init(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
        var frame:CGRect = self.frame
        frame.size.height = size.height
        self.frame = frame
    }
}

答案 8 :(得分:0)

Swift 3版Mundi的答案:

let maxHeight: CGFloat = 10000
let rect = label.attributedText!.boundingRect(with: CGSize(width: maxWidth, height: maxHeight),
                                                           options: .usesLineFragmentOrigin,
                                                           context: nil)
var frame = labe.frame
frame.size.height = rect.size.height
label.frame = frame

答案 9 :(得分:0)

我相信我有一个简单得多的解决方案:

let oldWidth = self.frame.size.width
label.sizeToFit()
label.frame.size.width = oldWidth

只需存储原来的宽度,sizeToFit()既适用于宽度,又适用于高度,然后将宽度重新设置为原来的值,而仅更改标签的高度。