Многострочная метка в UIStackView

154

При помещении многострочной метки (с переводом строки в Word Wrap) в представление стека метка сразу теряет перевод строки и отображает текст метки в одну строку.

Почему это происходит и как сохранить многострочную метку в виде стека?

благодеяние
источник
1
Вы установили количество строк в 0?
dasdom
Вы нашли ответ?
Бренден

Ответы:

204

Правильный ответ здесь:
https://stackoverflow.com/a/43110590/566360


  1. Вставить UILabelвнутри UIView(Редактор -> Вставить -> Просмотреть)
  2. Используйте ограничения , чтобы соответствовать UILabelк UIView(например, задний пространство, верхнее пространство, и ведущее пространство для SuperView ограничений)

UIStackViewБудет растянуть , UIViewчтобы соответствовать должным образом, и UIViewбудет сдерживать UILabelна несколько строк.

Энди
источник
36
Это так глупо, но это работает! Спасибо чувак ! Возможно, однажды Apple выпустит что-то, что не наполовину сломано в их SDK ...
Гийом Л.
1
О чувак! Вы спаситель! Я занимался этим часами :) Не забудьте также установить строки в 0 в Инспекторе атрибутов, пропускал только это.
Абсин
8
это обходной путь, правильное решение здесь stackoverflow.com/a/43110590/566360
vietstone
2
Мне было достаточно просто изменить горизонтальное выравнивание по центру. Нет UIViewмахинаций необходимо.
Шим
1
@Lucien это именно то, что было сказано в этом ответе. но правильный ответ здесь: stackoverflow.com/a/43110590/566360
Энди
145

Для горизонтального стека, который имеет UILabelодин из своих видов, в Interface Builder сначала установите label.numberOfLines = 0. Это должно позволить метке иметь более 1 строки. Это изначально не работало для меня, когда было представление стека stackView.alignment = .fill. Чтобы заставить его работать просто установите stackView.alignment = .center. Метка теперь может расширяться до нескольких строк в UIStackView.

Документация Apple гласит

Для всех выравниваний, кроме выравнивания заливки, представление стека использует внутреннее свойство Content Size каждого упорядоченного представления при расчете его размера перпендикулярно оси стека.

Обратите внимание на слово, кроме здесь. При .fillиспользовании горизонталь UIStackViewНЕ меняет размеры по вертикали, используя упорядоченные размеры подпредставлений.

постоянный репер
источник
3
Это правильное решение без хаков. Чтение документов всегда окупается!
Ислам Q.
3
Это должно быть принятым решением. С обходным решением UIView текст UILabel всплыл над другим подпредставлением в моем случае.
14
Это не работает на самом деле ... У меня есть 3 метки в моем стеке просмотра. Я установил линии на ноль и выровнял по центру ... Я все еще вижу, как метки обрезаются.
MatterGoal
11
Это .alignmentиз UIStackView , что вы должны установить к чему - либо , но .fill не UILabel, что немного смущает в данном примере label.alignment = .center. Я думаю, что это должно бытьstackView.alignment = .center
ae14
2
Но как я могу заставить работать несколько строк UILableView в вертикальном StackView?
Дахун
42
  • Сначала установите количество строк в метке 0
  • Представление стека по-прежнему не будет расти, multiLineпока вы не зададите ему фиксированную ширину. Когда мы фиксируем его ширину, он достигает многострочного, когда эта ширина достигается, как показано:

запись экрана

Если мы не дадим фиксированную ширину стековому виду, все станет неоднозначным. Как долго будет расти представление стека с меткой (если значение метки является динамическим)?

Надеюсь, что это может решить вашу проблему.

Ирфан
источник
3
Что, если ширина стекового представления не фиксирована, а пропорциональна ширине устройства (т.е. суперпредставления).
OutOnAWekend
Да, у нас тоже может быть пропорциональная ширина. Дело в том, что метка должна ломаться после некоторой ширины, какой бы она ни была, но должна быть определена.
Ирфан
@AnandKumar вы можете указать preferredMaxLayoutWidthв viewDidLayoutSubviewsдля метки в UIViewControllerили , layoutSubviewsесли подкласс UIView.
Шынгыс Касымов
4
Это должен был быть принятый ответ, весь смысл стека в том, чтобы не нужно было добавлять ограничения между стэком и его элементами ...
Дорогой,
4
Присвоение фиксированной стоимости побеждает цель автопоставки
Ислам Q.
17

Установка предпочитаемого MaxLayoutWidth для UILabel работала для меня

self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;
Пабло Мартинес
источник
3
Это правильный ответ в моей книге. Если вам когда-либо нужно связываться с UILabel и вам нужно обрабатывать несколько строк, вам действительно нужно присвоить ему предпочтительный MaxLayoutWidth. Это может работать без него, но без него все может стать довольно быстро.
Mof
2
Все перепробовали все ответы, и все они были не правы, кроме вашего. Спасибо!
Леван
Это прекрасно решило мою проблему и кажется намного менее хакерским, спасибо.
Итан Чжао
Спасибо за Ваш ответ! В моем случае выравнивание моего stackView уже было установлено, .centerи мне действительно не нужен был мой ярлык в UIView.
Фариза Жумат
12

Просто установите количество строк равным 0 в инспекторе атрибутов для метки. Это будет работать для вас.

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

technerd
источник
12
Для вертикального стека просмотра вам необходимо установить для параметра Распределение значение «Заполнить», чтобы это работало.
SnoopyProtocol
2
Установка Распределения на «Fill» является ключом к исправлению.
Дилан Мур
Я обнаружил, что для вертикального UIStackView мне пришлось установить верхние и нижние ограничения для дочернего UILabel, чтобы развернуть и показать весь текст.
bruce1337
8

Попробовав все вышеизложенное, я обнаружил, что для UIStackView не нужно менять свойства. Я просто изменяю свойства UILabels следующим образом (метки уже добавлены в представление вертикального стека):

Swift 4 пример:

    [titleLabel, subtitleLabel].forEach(){
        $0.numberOfLines = 0
        $0.lineBreakMode = .byWordWrapping
        $0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
    }
Билл Чан
источник
5

Магический трюк для меня было положить а widthAnchorв UIStackView.

Установка leadingAnchorи trailingAnchorне будет работать, но установка centerXAnchorи widthAnchorзаставила UILabel отображаться правильно.

Skoua
источник
4

iOS 9+

Позвоните [textLabel sizeToFit]после установки текста UILabel.

sizeToFit изменяет расположение многострочной метки, используя предпочитаемый параметр MaxWidth. Метка изменит размер stackView, который изменит размер ячейки. Никаких дополнительных ограничений, кроме прикрепления стека к представлению контента, не требуется.

aumansoftware
источник
4

Вот полный пример вертикали, UIStackViewсостоящей из многострочных UILabels с автоматической высотой.

Обтекание меток зависит от ширины стека и высоты стека зависит от обернутой высоты метки. (При таком подходе вам не нужно вставлять метки в UIView.) (Swift 5, iOS 12.2)

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

// A vertical stackview with multiline labels and automatic height.
class ThreeLabelStackView: UIStackView {
    let label1 = UILabel()
    let label2 = UILabel()
    let label3 = UILabel()

    init() {
        super.init(frame: .zero)
        self.translatesAutoresizingMaskIntoConstraints = false
        self.axis = .vertical
        self.distribution = .fill
        self.alignment = .fill

        label1.numberOfLines = 0
        label2.numberOfLines = 0
        label3.numberOfLines = 0
        label1.lineBreakMode = .byWordWrapping
        label2.lineBreakMode = .byWordWrapping
        label3.lineBreakMode = .byWordWrapping
        self.addArrangedSubview(label1)
        self.addArrangedSubview(label2)
        self.addArrangedSubview(label3)

        // (Add some test data, a little spacing, and the background color
        // make the labels easier to see visually.)
        self.spacing = 1
        label1.backgroundColor = .orange
        label2.backgroundColor = .orange
        label3.backgroundColor = .orange
        label1.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi."
        label2.text = "Hello darkness my old friend..."
        label3.text = "When I wrote the following pages, or rather the bulk of them, I lived alone, in the woods, a mile from any neighbor, in a house which I had built myself, on the shore of Walden Pond, in Concord, Massachusetts, and earned my living by the labor of my hands only."
    }

    required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}

Вот пример, ViewControllerкоторый использует это.

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let myLabelStackView = ThreeLabelStackView()
        self.view.addSubview(myLabelStackView)

        // Set stackview width to its superview.
        let widthConstraint  = NSLayoutConstraint(item: myLabelStackView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1, constant: 0)
        self.view.addConstraints([widthConstraint])
    }
}
zekel
источник
3

Добавить UIStackViewсвойства,

stackView.alignment = .fill
stackView.distribution = .fillProportionally
stackView.spacing = 8.0
stackView.axis = .horizontal

Вместо добавления метки внутри, UIViewкоторая не требуется. Если вы используете внутри, UITableViewCellпожалуйста, перезагрузите данные по ротации.

Сагар Даундкар
источник
3

Ниже приведена реализация многострочной метки на игровой площадке с разрывом строки внутри UIStackView. Он не требует встраивания UILabelчего-либо внутри и был протестирован с Xcode 9.2 и Swift 4. Надеюсь, это полезно.

import UIKit
import PlaygroundSupport

let containerView = UIView()
containerView.frame = CGRect.init(x: 0, y: 0, width: 400, height: 500)
containerView.backgroundColor = UIColor.white

var label = UILabel.init()
label.textColor = .black
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "This is an example of sample text that goes on for a long time. This is an example of sample text that goes on for a long time."

let stackView = UIStackView.init(arrangedSubviews: [label])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
containerView.addSubview(stackView)
stackView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
stackView.widthAnchor.constraint(equalTo: containerView.widthAnchor).isActive = true
stackView.heightAnchor.constraint(equalTo: containerView.heightAnchor).isActive = true

PlaygroundPage.current.liveView = containerView
JaredH
источник
1

Системный макет должен определять происхождение, ширину и высоту, чтобы нарисовать его подпредставления, в этом случае все ваши подпредставления имеют одинаковый приоритет, в этом случае возникают конфликты, система компоновки не знает зависимостей между представлениями, из которых одно рисует первым, вторым и т. Д.

Задать сжатие подпредставлений стека поможет решить проблему с несколькими строками, в зависимости от того, является ли ваше представление стека горизонтальным или вертикальным, и какое из них вы хотите сделать несколькими строками. stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal) lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

Трунг Фан
источник
0

В моем случае я следовал предыдущим предложениям, но мой текст все еще урезался до одной строки, хотя только в альбомной ориентации. Оказывается, я нашел невидимый \0нулевой символ в тексте метки, который был виновником. Должно быть, он был введен рядом с символом «тире», который я вставил. Чтобы увидеть, происходит ли это и в вашем случае, используйте View Debugger, чтобы выбрать вашу метку и проверить ее текст.

Джордан Х
источник
0

Xcode 9.2:

Просто установите количество строк в 0. Раскадровка будет выглядеть странно после установки этого. Не волнуйтесь, запустите проект. Во время работы все изменится в соответствии с настройками раскадровки. Я думаю, что это своего рода ошибка в раскадровке. введите описание изображения здесь

Советы: Установите «номер лайнера на 0» в последнем. сбросьте его, если вы хотите отредактировать другой вид и установите 0 после редактирования.

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

Сурендра Кумар
источник
0

Что сработало для меня!

stackview: выравнивание: заполнение, распределение: заполнение, ограничение пропорциональной ширине для суперпредставления ex. 0,8,

метка: центр и линии = 0

Михал Зиобро
источник
0

Для тех, кто до сих пор не может заставить это работать. Попробуйте установить Autoshrink с минимальной шкалой шрифтов на этой UILabel.

Скриншот UILabel Настройки автоусадки

Михал Мондик
источник
Попробуйте улучшить свой ответ с помощью примера кода.
Fridoo
1
@fridoo Добавлен скриншот настроек.
Михал Мондик
0

Это почти как @ Andy's Answer, но вы можете добавить свою UILabelдополнительную UIStackview, вертикальную для меня.

Запорожченко Александр
источник
0

Для меня проблема была в том, что высота стека была слишком короткой. Метка и представление стека были правильно настроены, чтобы метка могла иметь несколько строк, но метка стала первой жертвой сжатия содержимого, которое представление стека использовало для получения достаточно маленькой высоты.

Люк
источник