Багаторядкова мітка в UIStackView


154

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

Чому це відбувається і як зберегти багаторядкову мітку в межах подання стека?


1
Ви встановили кількість рядків 0?
dasdom

Ви знайшли відповідь?
Бренден

Відповіді:


204

Правильна відповідь тут:
https://stackoverflow.com/a/43110590/566360


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

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
Енді

144

Для подання горизонтального стека, який є UILabelодним із його поглядів, спочатку встановлено програму Interface Builder label.numberOfLines = 0. Це має дозволяти мітці мати більше 1 рядка. Спочатку це не спрацювало для мене, коли було представлено стек stackView.alignment = .fill. Щоб змусити його працювати просто встановити stackView.alignment = .center. Тепер мітка може розширюватися до кількох рядків у межах UIStackView.

Документація Apple говорить

Для всіх вирівнювань, за винятком вирівнювання заливки, у поданні стека використовується властивість властивості кожного розміщеного виду при обчисленні його розміру перпендикулярно осі стека

Зауважте слово, крім цього. При .fillвикористанні горизонталь UIStackViewНЕ змінює розміри вертикалі за допомогою розміщених розмірів підпогляду.


3
Це правильне рішення без злому. Читання документів завжди окупається!
Іслам Q.

3
Це має бути прийнятим рішенням. З обхідним способом UIView текст UILabel плив над іншим підглядом у моєму випадку.

14
Насправді це не працює ... У моєму стек-перегляді є 3 мітки. Я встановив рядки до нуля і вирівнювання до центру ... Я все ще бачу, як мітки вирізані.
MatterGoal

11
Це .alignmentUIStackView, що вам потрібно встановити що-небудь, але .fill не UILabel, що трохи заплутано в наведеному прикладі label.alignment = .center. Я думаю, що це має бутиstackView.alignment = .center
ae14,

2
Але як я можу змусити UILableView декількох ліній працювати у вертикальному StackView?
DàChún

42
  • Спочатку встановіть кількість рядків на етикетці 0
  • Перегляд стека все ще не зросте до multiLineтих пір, якщо ви не надасте йому фіксовану ширину. Коли ми фіксуємо його ширину, вона переривається на багаторядкову, коли ця ширина досягається, як показано:

запис на екрані

Якщо ми не надаємо фіксовану ширину виду стека, то все стає неоднозначним. Як довго зростатиме подання стека разом із міткою (якщо значення мітки динамічне)?

Сподіваємось, це може вирішити вашу проблему.


3
Що робити, якщо ширина подання стека не зафіксована, а натомість пропорційна ширині пристрою (тобто нагляду).
OutOnAWeekend

Так, ми можемо мати і пропорційну ширину. Справа в тому, якщо мітка повинна пробиватися через деяку ширину, яка б вона не була, але її потрібно визначити.
Ірфан

@AnandKumar ви можете вказати preferredMaxLayoutWidthв viewDidLayoutSubviewsдля мітки в UIViewControllerабо , layoutSubviewsякщо підклас UIView.
Shyngys Kassmov

4
Це має бути прийнятою відповіддю, вся суть перегляду стека полягає в тому, що не потрібно додавати обмежень між стеком перегляду та його елементами ...
Honey

4
Надання фіксованого значення перемагає мету авторозподілу
Іслам Q.

17

Налаштування перевагиMaxLayoutWidth для UILabel працювало для мене

self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;

3
Це правильна відповідь у моїй книзі. Коли ви колись зіпсуєтеся з UILabel і вам потрібно буде обробляти кілька рядків, вам дійсно потрібно надати йому перевагу MaxLayoutWidth. Це може спрацювати і без цього, але без цього все може стати досить привабливим.
Моф

2
Усі спробували всі відповіді, і всі вони помилялися, крім вашої. Дякую!
Леван

Це прекрасно вирішило мою проблему і відчуваєш себе набагато менш хакітним, дякую.
Етан Чжао

Дякую за вашу відповідь! У моєму випадку вирівнювання мого stackView вже було встановлено, .centerі мені дійсно не потрібна мітка в UIView.
Фаріза Жумат

12

Просто встановіть кількість рядків 0 в інспекторі атрибутів для мітки. Це буде працювати для вас.

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


12
Для вертикального stackView для цього вам потрібно встановити розподіл на "Заливка".
SnoopyProtocol

2
Встановлення розподілу на "Заповнити" - це ключ для виправлення.
Ділан Мур

Я виявив, що для вертикального 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 правильно.


4

iOS 9+

Дзвінок [textLabel sizeToFit]після встановлення тексту UILabel.

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


4

Ось повний приклад вертикалі, UIStackViewскладеної з багаторядковихUILabel s з автоматичною висотою.

Обертання міток виходячи з ширини стека, а висота стека базується на висоті загортання мітки. (При такому підході вам не потрібно вставляти мітки в a 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])
    }
}

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

1

Макет системи повинен визначати походження, ширину та висоту, щоб намалювати його підгляди; у цьому випадку всі ваші підпогляди мають однаковий пріоритет, цей момент робить конфлікт, система компонування не знає залежностей між видами, які малюють перший, другий і так далі

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


0

У моєму випадку я дотримувався попередніх пропозицій, але мій текст усе ще врізався в один рядок, хоча тільки в пейзажному стилі. Виявляється, я знайшов невидимого \0нульового символу в тексті лейбла, який був винуватцем. Це, мабуть, було введено поряд із символом em dash, який я вставив. Щоб дізнатись, чи трапляється це і у вашому випадку, скористайтеся відладчиком View, щоб вибрати свою мітку та переглянути її текст.


0

Xcode 9.2:

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

Поради: Останній встановіть "кількість вкладишів на 0". скиньте його, коли ви хочете відредагувати інший вид і встановити 0 після редагування.

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


0

Що для мене працювало!

stackview: вирівнювання: заповнення, розповсюдження: заповнення, обмеження пропорційна ширина до нагляду 0,8,

мітка: центр, а рядки = 0


0

Для тих, хто все ще не може змусити його працювати. Спробуйте встановити Автошинку з мінімальною шкалою шрифту на цьому UILabel.

Скріншот налаштувань автоматичної зшивки UILabel


Подумайте про покращення своєї відповіді на прикладі коду.
fridoo

1
@fridoo Додано скріншот налаштувань.
Michal Mondík


0

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

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