首页 文章

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

提问于
浏览
34
[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?

9 回答

  • 0

    这就是它的完成方式 . 因为标签已经包含字体信息,所以在这种方法中包含它是微不足道的 .

    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;
    

    Swift版本使用更新的 boundingRectWithSize

    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
    
  • 17

    您可以使用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

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

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

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

  • 39

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

    不过我认为 UILabel 的API可以改进 . 这就是为什么我认为一个类别将是最优雅的解决方案:

    //  UILabel+Resize.h
    @interface UILabel (Resize)
    - (void)sizeToFitHeight;
    @end
    
    //  UILabel+Resize.m
    @implementation UILabel (Resize)
    - (void)sizeToFitHeight {
        CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)];
        CGRect frame = self.frame;
        frame.size.height = size.height;
        self.frame = frame;
    }
    @end
    

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

    • sizeToFitHeight?

    • heightToFit?

    非常感谢评论,谢谢!

  • 1

    2017年答案......

    c = CGSize(width: yourWidth, height: 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
    

    而已 .


    很多时候,你想知道 difference in height compared to a "normal" one-line entry .

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

    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和标签之间交换;它会导致许多其他问题 . 苹果公司在写作时没有解决这个问题 . 解决问题很困难:以下方法通常都可以:

    @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

    (为清晰起见,添加了黄色 . )

  • 40

    商定的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
        }
    }
    
  • 1

    FIXED SOLUTION FOR 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
        }
    
    }
    
  • 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
        }
    }
    
  • 2

    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
    

相关问题