回答:
正解はこちら:https :
//stackoverflow.com/a/43110590/566360
UILabel
内部に埋め込むUIView
(エディタ->埋め込み->表示)UILabel
ためのUIView
トレーリングスペース、トップスペース、リーディングスペース)。UIStackView
伸ばしますUIView
適切にフィットし、かつUIView
制約されますUILabel
複数行に。
UIView
シェニガンは必要ありません。
UILabel
ビューの1つとしてがある水平スタックビューの場合、Interface Builderで最初に設定されlabel.numberOfLines = 0
ます。これにより、ラベルに複数の行を含めることができます。これは、スタックビューがあったときに最初は機能しませんでしたstackView.alignment = .fill
。機能させるには、単にを設定しstackView.alignment = .center
ます。ラベルは、UIStackView
。
アップルのドキュメントは言います
塗りつぶしの配置を除くすべての配置の場合、スタックビューは、スタックの軸に垂直なサイズを計算するときに、配置された各ビューの固有のContent Sizeプロパティを使用します
ここ以外の単語に注意してください。.fill
が使用される場合、水平UIStackView
は、配置されたサブビューのサイズを使用してそれ自体を垂直にサイズ変更しません。
.alignment
に設定する必要があるのは、UIStackViewのものです。私はこれはそうあるべきだと思います.fill
label.alignment = .center
stackView.alignment = .center
multiLine
固定幅を指定しない限り、スタックビューはまだ大きくなりません。幅を修正すると、次のようにその幅に達すると、複数行に分割されます。スタックビューに固定幅を指定しないと、あいまいになります。スタックビューは、ラベルとともにどのくらい長くなりますか(ラベル値が動的な場合)?
これで問題が解決することを願っています。
preferredMaxLayoutWidth
でviewDidLayoutSubviews
のあなたのラベルのためUIViewController
かにlayoutSubviews
あなたがサブクラス場合UIView
。
preferredMaxLayoutWidthをUILabelに設定するとうまくいきました
self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;
.center
おり、UIView内にラベルを本当に必要としませんでした。
上記のすべての提案を試した後、UIStackViewに必要なプロパティの変更はありませんでした。UILabelsのプロパティを次のように変更するだけです(ラベルは垂直スタックビューに既に追加されています)。
Swift 4の例:
[titleLabel, subtitleLabel].forEach(){
$0.numberOfLines = 0
$0.lineBreakMode = .byWordWrapping
$0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
}
iOS 9以降
コール [textLabel sizeToFit]
UILabelのテキストを設定した後にます。
sizeToFitは、preferredMaxWidthを使用してマルチラインラベルを再レイアウトします。ラベルは、セルのサイズを変更するstackViewのサイズを変更します。スタックビューをコンテンツビューに固定する以外に追加の制約は必要ありません。
UIStackView
マルチラインで構成される垂直の完全な例は次のとおりですUILabel
自動高さの。ラベルはスタックビューの幅に基づいて折り返され、スタックビューの高さはラベルの折り返された高さに基づいています。(このアプローチでは、ラベルを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])
}
}
以下は、内に改行を含む複数行ラベルのPlayground実装です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
システムレイアウトは、サブビューを描画するために、原点、幅、高さを把握する必要があります。この場合、すべてのサブビューは同じ優先度を持ち、そのため競合が発生します。レイアウトシステムはビュー間の依存関係を認識していません。
スタックサブビューの圧縮を設定すると、スタックビューが水平または垂直で、どれを複数行にしたいかに応じて、複数行の問題が解決されます。 stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal)
lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
それはほとんどアンディの回答@のようなものだが、あなたはあなたを追加することができますUILabel
余分にUIStackview
私のために働いた垂直、。