webentwicklung-frage-antwort-db.com.de

Mehrzeiliges Etikett in UIStackView

Wenn Sie ein mehrzeiliges Label (mit Zeilenumbruch auf Word Wrap) in eine Stapelansicht setzen, verliert das Label sofort den Zeilenumbruch und zeigt stattdessen den Etikettentext in einer Zeile an.

Warum geschieht dies und wie werden mehrzeilige Beschriftungen in einer Stapelansicht beibehalten? 

87
Boon

Die richtige Antwort ist hier: https://stackoverflow.com/a/43110590/566360

  1. Betten Sie UILabel in ein UIView (Editor -> Einbetten in -> Ansicht) ein
    1. Verwenden Sie Einschränkungen, um das UILabel an das UIView anzupassen (z. B. abschließender Speicherplatz, oberster Speicherplatz und führender Platz für Superview-Einschränkungen).

Das UIStackView dehnt das UIView aus, um richtig zu passen, und das UIView zwingt das UILabel zu mehreren Zeilen.

125
Andy

Für eine horizontale Stapelansicht, die eine UILabel als eine ihrer Ansichten hat, setzen Sie zunächst im Interface Builder label.numberOfLines = 0. Dadurch sollte das Etikett mehr als eine Zeile haben. Dies funktionierte anfangs nicht für mich, als die Stack-Ansicht stackView.alignment = .fill hatte. Damit dies funktioniert, setzen Sie einfach stackView.alignment = .center. Die Beschriftung kann jetzt in der UIStackView auf mehrere Zeilen erweitert werden.

Die Apple-Dokumentation sagt 

Für alle Ausrichtungen außer der Füllungsausrichtung verwendet die Stapelansicht jede Die intrinsische Eigenschaft "Content Size" der geordneten Ansicht bei der Berechnung ihrer Größe senkrecht zur Achse des Stapels

Beachten Sie das Wort außer hier. Bei Verwendung von .fill ändert sich die horizontale UIStackView NICHT vertikal in der Größe der arrangierten Unteransichten.

52
pbm
  • Setzen Sie zunächst die Beschriftungsnummer der Zeilen auf 0
  • Die Stapelansicht wird nicht zu multiLine wachsen, wenn Sie keine feste Breite angeben. Wenn wir die Breite festlegen, wird die Linie in mehrere Zeilen unterteilt, wenn diese Breite erreicht ist.

 screen recording

Wenn wir der Stack-Ansicht keine feste Breite geben, werden die Dinge mehrdeutig. Wie lange wächst die Stack-Ansicht mit der Beschriftung (wenn der Beschriftungswert dynamisch ist)?

Hoffe, das kann dein Problem beheben.

40
Irfan

Setzen Sie im Attribut-Inspektor für die Beschriftung die Anzahl der Zeilen auf 0. Es wird für Sie arbeiten.

 enter image description here

11
technerd

Das Folgende ist eine Playground-Implementierung eines mehrzeiligen Labels mit einem Zeilenumbruch in einer UIStackView. Es ist nicht erforderlich, die Variable UILabel in etwas einzubetten und wurde mit Xcode 9.2 und Swift 4 getestet. Ich hoffe, es ist hilfreich.

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
3
JaredH

Hier ist ein vollständiges Beispiel für eine vertikale UIStackView, die aus mehrzeiligen UILabels mit automatischer Höhe besteht.

Der Etikettenumbruch basiert auf der Breite der Stapelansicht und die Höhe der Stapelansicht basiert auf der Höhe des Etikettenumbruchs. (Bei diesem Ansatz müssen Sie die Beschriftungen nicht in UIView einbetten.) (Swift 5, iOS 12.2)

enter image description here

// 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") }
}

Hier ist ein Beispiel ViewController, das es verwendet.

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])
    }
}
2
zekel

Der Zaubertrick für mich bestand darin, eine widthAnchor auf die UIStackView zu setzen.

Die Einstellung von leadingAnchor und trailingAnchor funktioniert nicht, aber die Einstellung von centerXAnchor und widthAnchor hat die Anzeige der UILabel richtig gemacht.

2
Skoua

Fügen Sie UIStackView-Eigenschaften hinzu.

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

Anstatt ein Label in UIView hinzuzufügen, das nicht erforderlich ist. Wenn Sie in UITableViewCell verwenden, laden Sie die Daten bei der Rotation erneut.

2
Sagar Daundkar

iOS 9+ 

Rufen Sie [textLabel sizeToFit] auf, nachdem Sie den UILabel-Text festgelegt haben. 

sizeToFit gestaltet das mehrzeilige Label mit PreferredMaxWidth neu. Das Label ändert die Größe der StackView, wodurch die Zelle verkleinert wird. Neben dem Fixieren der Stapelansicht mit der Inhaltsansicht sind keine zusätzlichen Einschränkungen erforderlich.

1
aumansoftware

Das Setzen von preferredMaxLayoutWidth auf das UILabel hat für mich funktioniert

self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;
1
Pablo Martinez

Das Systemlayout sollte Ursprung, Breite und Höhe bestimmen, um Unteransichten zu zeichnen. In diesem Fall haben alle Unteransichten die gleiche Priorität. Dies führt zu Konflikten. Das Layoutsystem kennt keine Abhängigkeiten zwischen den Ansichten, die man zuerst, dann und so weiter zeichnet

Wenn Sie die Komprimierung für Stapel-Unteransichten festlegen, wird das Problem mit mehreren Zeilen behoben. Dies hängt davon ab, ob die Stapelansicht horizontal oder vertikal ist und aus welcher mehrere Zeilen bestehen sollen. stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal)lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

1
Trung Phan

Es ist fast wie bei Andy's Answer, aber du kannst dein UILabel in extra UIStackview einfügen, vertikal hat für mich gearbeitet.

In meinem Fall folgte ich den vorherigen Vorschlägen, aber mein Text wurde immer noch auf eine einzige Zeile gekürzt, allerdings nur im Querformat. Es stellte sich heraus, dass ich im Text des Etiketts ein unsichtbares \0-Nullzeichen gefunden habe, das der Täter war. Es muss neben dem Em-Strich-Symbol eingeführt worden sein, das ich eingefügt hatte. Um zu sehen, ob dies auch in Ihrem Fall der Fall ist, verwenden Sie den View Debugger, um Ihr Label auszuwählen und seinen Text zu überprüfen.

0
Jordan H

Was hat bei mir funktioniert?

stapelansicht: Ausrichtung: Füllen, Verteilen: Füllen, Beschränkung proportional Breite zum Sup. 0,8 

beschriftung: Mitte und Zeilen = 0

0
Michał Ziobro

Nachdem ich alle obigen Vorschläge ausprobiert hatte, stellte ich fest, dass für UIStackView keine Änderungen der Eigenschaften erforderlich sind. Ich ändere einfach die Eigenschaften der UILabels wie folgt (Die Beschriftungen werden bereits zu einer vertikalen Stapelansicht hinzugefügt):

Swift 4 Beispiel:

    [titleLabel, subtitleLabel].forEach(){
        $0.numberOfLines = 0
        $0.lineBreakMode = .byWordWrapping
        $0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
    }
0
Bill Chan

Xcode 9.2:

Legen Sie einfach die Anzahl der Zeilen auf 0 fest. Das Storyboard sieht nach der Einstellung seltsam aus. Mach dir keine Sorgen das Projekt auszuführen. Während der Ausführung wird alles entsprechend der Storyboard-Konfiguration angepasst. Ich denke, es ist ein Fehler im Storyboard .  enter image description here

Tipps: Legen Sie zuletzt "Liner-Nummer auf 0" fest. Setzen Sie sie zurück, wenn Sie eine andere Ansicht bearbeiten möchten, und setzen Sie sie nach der Bearbeitung auf 0.

 enter image description here

0
Surendra Kumar

Für alle, die es immer noch nicht schaffen. Versuchen Sie, Autoshrink mit einer minimalen Schriftgröße für dieses UILabel festzulegen.

Screenshot UILabel Autoshrink-Einstellungen

0
Michal Mondík