Подтвердить что ты не робот

Как изменить размер UILabel, изменив только высоту, а не ширину?

[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>>

Я знаю, что есть способ сделать это с помощью: Как настроить и сделать ширину UILabel в соответствии с размером текста?

Ответы либо странные (нам нужно пополнить информацию о шрифте). Или неясно.

Вам также необходимо определить максимальную ширину и сообщить своей программе что делать, если sizeToFit дает вам ширину больше этого максимума.

Я использую странное решение использования sizeWithFont. Странно, потому что UILabel уже знает шрифт в ярлыке.

Вообще-то, как ведет себя режим sizeToFit? Как он решает, нужен ли нам более тонкий или более высокий UILabel?

4b9b3361

Ответ 1

Вот как это делается. Поскольку метка уже содержит информацию о шрифте, включая ее в этом вызове метода, тривиально.

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:

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

Ответ 2

Вы можете добиться того же результата с помощью 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;

Ответ 3

sizeToFit отлично работает. Единственная проблема заключается в том, что он основан на текущем размере элемента управления.

Например, если вы перебираете ячейки таблицы с меткой, метка может быть уменьшена по ширине в предыдущей ячейке, и поэтому вызов sizeToFit может выглядеть ненадежным.

Просто reset исходная ширина вашего элемента управления перед отправкой сообщения sizeToFit.

Ответ 4

Я думаю, вы не должны использовать методы NSString size..., UILabel уже имеет API для этого, как указывает @vatrif (который, вероятно, использует только методы NSString).

Тем не менее, я думаю, что API UILabel можно было бы улучшить. Вот почему я считаю, что категория будет самым элегантным решением:

//  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?

Комментарии очень ценятся, спасибо!

Ответ 5

Ответ на 2017...

c = CGSize (ширина: ваша ширина, высота: 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

Что это.


Очень часто вы хотите знать разницу высот по сравнению с "нормальной" однострочной записью.

Это особенно важно, если вы создаете какие-то ячейки, которые не имеют ничего общего с UTableView (скажем, какое-то представление пользовательского стека). Вы должны установить высоту вручную в какой-то момент. На своем раскадровке создайте его по своему усмотрению, используя образец текста любой короткой строки (например, "А" ), которая, конечно же, будет иметь только одну строку в любой нормальной ситуации. Затем вы делаете что-то вроде этого...

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;
    }
}

Сломанный, непригодный UITextView от Apple...

введите описание изображения здесь

UITextViewFixed, который в большинстве случаев является приемлемым исправлением:

введите описание изображения здесь

(Желтый добавлен для ясности.)

Ответ 6

Согласованный API выиграет от этого добавления. Сделайте вашу жизнь проще и добавьте расширение к классу UILabel в Swift следующим образом:

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
    }
}

Ответ 7

ФИКСИРОВАННОЕ РЕШЕНИЕ ДЛЯ 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
    }

} 

Ответ 8

Легкое расширение для этой задачи для 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
    }
}

Ответ 9

Свифт 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

Ответ 10

Я считаю, что у меня есть намного более простое решение:

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

Просто сохраните прежнюю ширину, sizeToFit() применимо как к ширине, так и к высоте, затем сбросьте ширину обратно к старому значению, оставив только измененную высоту метки.