忘備録です。
sizeToFit()の仕様で躓いて悩んだので、どういう感じでどう解決するに至ったのか、書いておきます。
リファレンスにはaddSubViewの後にsizeToFitしろって書いてはありますが、この現象については書いてないですね…。
前提
- swift4.2,xcode10
- UILabelをコードで生成
- 高さ、幅を動的に計算して同じView内に配置
- UILabelの個数はデータによって変わり、確定していない
- 配置すると言っても前のものの下に配置する形
やったこと
- viewDidLoad()で処理
- sizeToFit()
- labe.bound.size.heightで高さを取る
- 変数offsetに+=してy位置を指定する
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
(中略)
for nLoop in 0 ... labelTextData.count - 1 {
let label = UILabel()
label.numberOfLines = 0
// ラベルのフォントのオートシュリンクの設定
label.adjustsFontForContentSizeCategory = true
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.3
// font
if let customFont = UIFont(name: "Chalkboard SE", size: 17) {
label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: customFont)
} else {
label.font = UIFont.preferredFont(forTextStyle: .body)
}
label.text = labelTextData[nLoop].1
// viewにラベルを追加
// constraintsよりも前に追加する必要があるらしい
view.addSubview(label)
// AutoLayoutとバッティングしないためFalse
label.translatesAutoresizingMaskIntoConstraints = false
// constraints
label.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8).isActive = true
label.sizeToFit()
// 大本のViewとX軸中心合わせ
label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
// Top Anchorは大本のViewに合わせる(オフセットでずらす。)
label.topAnchor.constraint(equalTo: view.topAnchor, constant: offset).isActive = true
offset += label.bounds.size.height
}
}
結果
- ラベルの内容は表示されるがheightで取れる値が合わずに重なる
- ラベルの内容によってずれる高さは変わってくる
迷走
- UIImageViewに画像突っ込んだらどうなるの?と試して爆死
- CGRectでUIImageViewを設定したら…駄目
- Constraintsの設定?…違う
- UIImageをリサイズしてサイズを確定、Viewも同じサイズで成功
- Contsraintsの問題?違うっぽい
- sizeToFit()の位置の問題?元から位置はあってそう
- text,font等を設定してからsizeToFit()でOK
- もうめんどくさいオフセットの値に足したれ!
- 当たり前だけどもきれいには行かない
- やっぱりちゃんと値を取れるようになろう…。
- UIImageの時のように先に大きさを指定したらどうかな
- frameにCGRectでサイズ指定は可能
- InterfaceBuilderだと先に小さいのが出てくるから小さく…駄目
- 大きくするにしても横幅は決まってるから、高さを大きく…成功
結論
- label.frameにCGRectで先に矩形を指定し、その後sizeToFit()
- heightの値を中に入るテキストよりも絶対に大きくなるように設定
// 一度大きく高さを設定してからSizetofitで小さく収めないと正確な値が出てこない
label.frame = CGRect(x: 0 ,y: offset, width: screenWidth * 0.8, height: sceenHeight * 10)
まさかこんな仕様が隠れていたとは…。
会社とかで複数人でやってるならばうまくいかないとか話してれば情報共有で知ってる人からすぐ教えてもらえるケースな気がします。