複数行のラベル(改行をワードラップに設定)をスタックビューに配置すると、ラベルはすぐに改行を失い、代わりにラベルテキストを1行で表示します。
なぜこれが起こり、スタックビュー内で複数行ラベルをどのように保持するのですか?
正解はこちら: https://stackoverflow.com/a/43110590/56636
UILabel
をUIView
内に埋め込みます(エディター->埋め込み->表示)UILabel
をUIView
に合わせます(たとえば、末尾のスペース、上部のスペース、およびスーパービューの制約の先頭のスペース)。UIStackView
は適切に収まるようにUIView
を伸ばし、UIView
はUILabel
を複数行に制限します。
ビューの1つとしてUILabel
を持つ水平スタックビューの場合、Interface Builderで最初にlabel.numberOfLines = 0
を設定します。これにより、ラベルに複数の行を含めることができます。スタックビューにstackView.alignment = .fill
が含まれていた場合、これは最初は機能しませんでした。動作させるには、単にstackView.alignment = .center
を設定します。これで、ラベルはUIStackView
内で複数行に展開できます。
塗りつぶし配置を除くすべての配置について、スタックビューは、スタックの軸に垂直なサイズを計算するときに、配置された各ビューの組み込みのContentSizeプロパティを使用します
ここでWordexceptに注意してください。 .fill
を使用すると、水平のUIStackView
は、配置されたサブビューのサイズを使用して、垂直方向にサイズを変更しません。
PreferredMaxLayoutWidthをUILabelに設定するとうまくいきました
self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;
iOS 9以降
UILabelのテキストを設定した後、[textLabel sizeToFit]
を呼び出します。
sizeToFitは、preferredMaxWidthを使用して複数行ラベルを再レイアウトします。ラベルはstackViewのサイズを変更し、セルのサイズを変更します。スタックビューをコンテンツビューに固定する以外の追加の制約は必要ありません。
以下は、UIStackView
内に改行がある複数行ラベルのPlayground実装です。 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
UIStackView
sで構成される垂直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])
}
}
私にとっての魔法は、widthAnchor
をUIStackView
に設定することでした。
leadingAnchor
およびtrailingAnchor
を設定しても機能しませんが、centerXAnchor
およびwidthAnchor
を設定すると、UILabelが正しく表示されます。
UIStackView
プロパティを追加し、
stackView.alignment = .fill
stackView.distribution = .fillProportionally
stackView.spacing = 8.0
stackView.axis = .horizontal
UIView
内にラベルを追加するのではなく、UITableViewCell
内で使用している場合は、ローテーション時にデータをリロードしてください。
上記のすべての提案を試した後、UIStackViewのプロパティを変更する必要がないことがわかりました。 UILabelsのプロパティを次のように変更するだけです(ラベルは既に垂直スタックビューに追加されています)。
Swift 4の例:
[titleLabel, subtitleLabel].forEach(){
$0.numberOfLines = 0
$0.lineBreakMode = .byWordWrapping
$0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
}
システムレイアウトは、サブビューを描画するために、Origin、幅、高さを把握する必要があります。この場合、すべてのサブビューは同じ優先順位を持ち、その点で競合が発生します。
スタックサブビューの圧縮を設定すると、スタックビューが水平か垂直か、どの行を複数行にするかに応じて、複数行の問題を解決できます。 stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal)
lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
@ Andy's Answerとほぼ同じですが、UILabel
を追加のUIStackview
に追加できます。
私の場合、以前の提案に従いましたが、テキストは横向きだけでしたが、まだ1行に切り捨てられていました。ラベルのテキストに、目に見えない\0
null文字が原因であることがわかりました。それは私が挿入したemダッシュ記号と一緒に導入されたに違いありません。これがケースでも発生しているかどうかを確認するには、View Debuggerを使用してラベルを選択し、そのテキストを調べます。
私のために働いたもの!
stackview:配置:塗りつぶし、分布:塗りつぶし、superviewへの比例幅の制限ex。 0.8、
ラベル:中央、ライン= 0
まだそれを機能させることができない人のために。そのUILabelの最小フォントスケールで自動縮小を設定してみてください。