Налаштуйте висоту UILabel до тексту


112

У мене є кілька міток, які я хочу відрегулювати їх висоту до тексту, це код, який я зараз для цього написав

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
}

Редагувати:

Питання не було в цьому фрагменті коду, тому моє виправлення полягає в самому питанні. Це може бути корисно для інших!


Погляньте на доповнення NIKtring UIKit, там є методи для розрахунку розміру, як вам потрібно, не створюючи UILabel.
Володимир Гриценко

@VladimirGritsenko методи "sizeWithFont" недоступні у Swift :(
TheBurgerShot

Я визнаю, що я не фахівець зі Свіфта, але я вважаю, що ви можете додати свої власні способи з'єднання. Все-таки варто було б над створенням UILabel для обчислення розміру.
Володимир Гриценко

@TheBurgerShot sizeWithFontможе бути недоступний для Swift, Stringале він доступний на. NSStringВи все одно зможете зателефонувати за цим.
Анорак

Зрештою, помилка була чимось іншою і не мала нічого спільного з цим методом. Хоча це все ще може бути корисним для інших.
TheBurgerShot

Відповіді:


189

Я щойно поставив це на дитячому майданчику, і це працює на мене.

Оновлено для 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
}

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


це добре працює для мене теж на дитячій площадці, здається, помилка не виникає в цьому конкретному місці, коли я видаляю звичаї цього методу, він збиратиметься про деякі println або просто рядок з лише коментарями (тоді він говорить EXC_BAD_ACCESS код = 2 також)
TheBurgerShot

6
Він працює на ігровому майданчику, але розмір розмірів не відбувається за бажанням всередині контролера перегляду в XCode 6.1
Unome

1
Я трохи вагаюся створити новий UILabelза розмірами; якщо цей метод застосовується всередині layoutSubviewsз тенденцією викликати кілька разів за повний макет, створення додаткового об'єкта може спричинити помітні затримки, особливо під час прокрутки.
Зорайр

нехай textRect = textString.boundingRectWithSize (CGSizeMake (320, 2000), параметри: .UsesLineFragmentOrigin, атрибути: textAttributes, context: nil)
Siddharth Pancholi

Я не можу викликати цю функцію в моєму контролері перегляду ... Чи можете ви запропонувати мені, що могло бути причиною?
Rouny

64

Якщо ви використовуєте AutoLayout , ви можете налаштувати UILabelвисоту лише за допомогою конфігураційного інтерфейсу.

Для iOS8 або вище

  • Встановіть обмеження, що ведуть / відкладають для себе UILabel
  • І змінити рядки UILabelвід 1 до 0

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

Для iOS7

  • Спочатку потрібно додати висоту дляUILabel
  • Потім змініть відношення з EqualдоGreater than or Equal

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

  • Нарешті , змініть рядки UILabelвід 1 до 0

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

Ваш UILabelбуде автоматично збільшувати висоту в залежності від тексту


2
І якщо етикетка знаходиться всередині комірки. Коли і як би ви відповідно збільшили висоту комірки?
oyalhi

1
@oyalhi, якщо ваш ярлик знаходиться у комірці перегляду таблиць, перегляньте мою іншу публікацію stackoverflow.com/a/36277840/5381331
Phan Van Linh

3
Це прекрасно працювало для мене! Встановіть обмеження, і воно буде справно працювати!
Білл Томпсон

2
не працює для мене ... слово "Мітка" в UILabel складає висоту = 20. Залишилося 20 після цього налаштування.
gadget00

9

Я створюю це розширення, якщо хочете

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

8

У мене є міцне робоче рішення.

в layoutSubviews:

    _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

6

Просто встановивши:

label.numberOfLines = 0

Етикетка автоматично регулює свою висоту залежно від кількості введеного тексту.


27
Це не змушує UILabel регулювати свою висоту.
TheBurgerShot

6

Виходячи з відповіді Анорака, я також погоджуюся із занепокоєнням Зорайра, тому я додав пару рядків, щоб видалити 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
}

5

У швидкій 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)

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' - це властивість лише для отримання.
Amg91

4

Після відповіді на @Anorak, я додав це розширення до String і надіслав вкладку як параметр, тому що багато разів вам знадобиться прокладка до тексту. У будь-якому випадку, можливо, ви знайдете це корисним.

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.ByWordЗмінення цього рядка допомогло мені спасибі.
Coder_A_D

3

Ось як обчислити висоту тексту в Swift. Потім можна отримати висоту від прямої і встановити висоту обмеження мітки чи 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)

3

просто зателефонуйте цьому методу там, де вам потрібна динамічна висота для мітки

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
}

3

Swift 4.0

self.messageLabel = UILabel (кадр: CGRect (x: 70, y: 60, ширина: UIScreen.main.bounds.width - 80, висота: 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()

Блокувати котирування NSParagraphStyle.LineBreakMode, застосовувати до цілих абзаців, а не до слів у параграфах. Це властивість діє як під час звичайного малювання, так і у випадках, коли розмір шрифту повинен бути зменшений, щоб відповідати тексту мітки в обмежувальному полі. За цією властивістю за замовчуванням встановлено значенняTruncatingTail.

Це посилання описує спосіб виконання розповіді, як це зробити


2
Відповіді, що стосуються лише коду, не вважаються хорошою практикою. Будь ласка, подумайте, щоб додати деякі пояснення того, як ваша відповідь відповідає на це питання.
Янніс

2

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

2

Метод розширення 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
    }

}

1

Swift 5, XCode 11. Я думаю, що це працює для iOS 9 і новіших версій. Наприклад, ви хочете, щоб мітка "Опис" отримувала динамічну висоту, виконайте кроки:

1) Виберіть етикетку опису -> Перейдіть до інспектора атрибутів (піктограма олівця), встановіть: Рядки: 0 Розрив рядка: Обертання слів

2) Виберіть свій UILabel з аркуша розкадрування та перейдіть до інспектора розміру (піктограма лінійки); 3) Перейдіть до пункту «Пріоритет стиснення вмісту до 1 для всіх інших компонентів UIView (мітки, кнопки, перегляд зображень тощо), які взаємодіють із вашою міткою.

Наприклад, у мене є вертикально UIImageView, мітка заголовка та мітка опису вертикально. Я встановив пріоритет стійкості до стиснення вмісту для UIImageView і мітки заголовка до 1, а для мітки опису - до 750. Це дозволить зробити мітку опису настільки ж потрібною висоти.


0

Щоб швидко зробити ярлик динамічним, не вказуйте константи висоти, а на аркуші розкадровки зробіть кількість міток рядків 0 і надайте обмеження на нижній частині, і це найкращий спосіб, коли я обробляю динамічну мітку відповідно до їх розміру вмісту.


0

Ви також можете використовувати sizeThatFitsфункцію.

Наприклад:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.