2017-11-09 4 views
1

Ich möchte 2 Labels (zB leftLabel, rightLabel) und lege sie horizontal, so dass leftLabel streckt und rightLabel nur ein einzelnes Zeichen passt (sagen wir ">"). Somit sind beide Etiketten Layout gerechtfertigt. So ...Programmatisch erstelltes horizontales UIStackView mit 2 selbsterstellten Labels

enter image description here

Dies ist der Code, den ich habe -

class StackViewController: UIViewController { 
    /// Main vertical outer/container stack view that pins its edges to this view in storyboard (i.e. full screen) 
    @IBOutlet weak private var containerStackView: UIStackView! 

    private var leftLabel: UILabel = { 
     let leftLabel = UILabel(frame: .zero) 
     leftLabel.font = .preferredFont(forTextStyle: .body) 
     leftLabel.numberOfLines = 0 // no text truncation, allows wrap 
     leftLabel.backgroundColor = .orange 
     return leftLabel 
    }() 
    private var rightLabel: UILabel = { 
     let rightLabel = UILabel(frame: .zero) 
     rightLabel.font = .preferredFont(forTextStyle: .body) 
     // Set CHCR as high so that label sizes itself to fit the text 
     rightLabel.setContentHuggingPriority(UILayoutPriorityDefaultHigh, for: .horizontal) 
     rightLabel.setContentCompressionResistancePriority(UILayoutPriorityDefaultHigh, for: .horizontal) 
     rightLabel.backgroundColor = .green 
     return rightLabel 
    }() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     prepareAndLoadSubViews() 
     // Note, the text required to be set in viewDidAppear, not viewDidLoad, otherwise rightLabel stretches to fill!! 
     leftLabel.text = "This is left label text that may go in multiple lines" 
     rightLabel.text = ">" // Always a single character 
    } 

    /// Dynamically creates a horizontal stack view, with 2 labels, in the container stack view 
    private func prepareAndLoadSubViews() { 
     /// Prepare the horizontal label stack view and add the 2 labels 
     let labelStackView = UIStackView(arrangedSubviews: [leftLabel, rightLabel]) 
     labelStackView.axis = .horizontal 
     labelStackView.distribution = .fillProportionally 
     labelStackView.alignment = .top 
     containerStackView.addArrangedSubview(labelStackView) 
     containerStackView.addArrangedSubview(UIView()) 
    } 
} 

Welche unten Ergebnis gibt (dh leftLabel Breite ist 0 im Hinblick Debugger) -

enter image description here

Hinweis: Wenn ich Text setzen Code in ViewDidAppear verschieben, dann funktioniert es gut.

override func viewDidAppear(_ animated: Bool) { 
    super.viewDidAppear(animated) 
    // Note, the text required to be set in viewDidAppear, not viewDidLoad, otherwise rightLabel stretches to fill!! 
    leftLabel.text = "This is left label text that may go in multiple lines" 
    rightLabel.text = ">" // Always a single character 
} 

Warum? Und können wir vor dem ViewDidLoad Prioritäten bei der Inhaltsanpassung/Komprimierung setzen?

Antwort

0

Ich habe mit deinem Code ziemlich herumgespielt, aber ich konnte es auch nicht funktionieren lassen. Ich denke, das ist ein Fehler, der auftritt, wenn Sie einen UIStackView zu einem anderen UIStackView hinzufügen. Wenn Sie nur eine UIStackView haben, funktioniert Ihr Code einwandfrei.

So kann ich keine Lösung für Ihren Fall bieten, aber IMHO sollten Sie nicht wirklich eine UIStackView für Ihre 2 Etiketten überhaupt verwenden müssen. UIStackView ist großartig, wenn Sie mehrere angeordnete Unteransichten haben, die Sie ausblenden und anzeigen und die automatisch angeordnet werden müssen. Für nur zwei "statische" Labels halte ich das für etwas Overkill.

Sie können erreichen, was Sie wollen, indem Sie Ihre zwei Etiketten zu einer UIView hinzufügen und dann Layout-Einschränkungen für die Etiketten festlegen. Es ist wirklich einfach:

class StackViewController: UIViewController { 

    @IBOutlet weak var containerStackView: UIStackView! 

    private var leftLabel: UILabel = { 
     let leftLabel = UILabel(frame: .zero) 
     leftLabel.font = .preferredFont(forTextStyle: .body) 
     leftLabel.numberOfLines = 0 
     leftLabel.backgroundColor = .orange 
     leftLabel.translatesAutoresizingMaskIntoConstraints = false 
     leftLabel.numberOfLines = 0 
     return leftLabel 
    }() 
    private var rightLabel: UILabel = { 
     let rightLabel = UILabel(frame: .zero) 
     rightLabel.font = .preferredFont(forTextStyle: .body) 
     rightLabel.setContentHuggingPriority(UILayoutPriority.required, for: .horizontal) 
     rightLabel.backgroundColor = .green 
     rightLabel.translatesAutoresizingMaskIntoConstraints = false 
     return rightLabel 
    }() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     prepareAndLoadSubViews() 
     leftLabel.text = "This is left label text that may go in multiple lines" 
     rightLabel.text = ">" 
    } 

    private func prepareAndLoadSubViews() { 
     let labelContainerView = UIView() 
     labelContainerView.addSubview(leftLabel) 
     labelContainerView.addSubview(rightLabel) 

     NSLayoutConstraint.activate([ 
      leftLabel.leadingAnchor.constraint(equalTo: labelContainerView.leadingAnchor), 
      leftLabel.topAnchor.constraint(equalTo: labelContainerView.topAnchor), 
      leftLabel.bottomAnchor.constraint(equalTo: labelContainerView.bottomAnchor), 

      rightLabel.leadingAnchor.constraint(equalTo: leftLabel.trailingAnchor), 
      rightLabel.topAnchor.constraint(equalTo: labelContainerView.topAnchor), 
      rightLabel.bottomAnchor.constraint(equalTo: labelContainerView.bottomAnchor), 
      rightLabel.trailingAnchor.constraint(equalTo: labelContainerView.trailingAnchor) 
     ]) 

     containerStackView.addArrangedSubview(labelContainerView) 
     containerStackView.addArrangedSubview(UIView()) 
    } 
} 
+0

Vielen Dank für das Ausprobieren und den Rat. Sie haben Recht, ich kann das gleiche Layout mit Einschränkungen erreichen. Aber ich habe zusätzliche Anforderungen, um RightLabel basierend auf Daten zu verbergen, d. H. LeftLabel sollte sich auf die volle Breite erstrecken. Um dies durch das automatische Layout zu erreichen, werden nur wenige zusätzliche Einschränkungen benötigt. Außerdem müsste ich in dieser Zelle in der Regel einige weitere Labels/imageview hinzufügen, also würde ich * lieber * Stack View als Constraints verwenden. – Ashok

Verwandte Themen