少し、突っかかって悩んだのと、メモとして残しておきたいのでまとめておきます。
[Auto Layoutをコードで書いてみた][link]
[link]:https://qiita.com/dddisk/items/8001598ea7951bcdcc30
設定出来るConstraintsとか、translatesAutoresizingMaskIntoConstraintsとは何かについては基本的にこの記事が詳しかったので、省きます。
フレキシブルにラベル等を表示したい
- View上に、フレキシブルにラベルなんかを表示したい。(要らないときは表示したくない、スケーリングもしたい)
要らないときは、という部分についてはコードで生成すれば解決、ということで特に迷いませんでした。
スケーリングについてはEqualHeightsとかその手のものを利用してストーリーボード上で既に出来ていましたし、NSLayoutAnchorにすぐに辿り着いたのでそこらへんもおおよそ問題ありませんでした。
ただ、幾つか引っかかったのが、Constraints設定とViewへのオブジェクト追加の順番と、上端や左端の%値での設定、Autorisizingのフラグ設定でした。
生成〜設定の順序
// ラベルを生成
let label = UILabel()
label.text = "やらないか"
// fontのオートシュリンクの設定
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.3
// font
if let customFont = UIFont(name: "Bradley Hand", size: UIFont.labelFontSize) {
label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: customFont)
} else {
label.font = UIFont.preferredFont(forTextStyle: .body)
}
// viewにラベルを追加
// constraintsよりも前に追加する必要がある
view.addSubview(labNone)
// AutoresizingMaskの設定値を使うとバッティングするのでフラグをfalseにする
label.translatesAutoresizingMaskIntoConstraints = false
// constraints
// 大本のViewとX軸中心合わせ
label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
// 大本のViewとY軸合わせ。
// 1/2を3/8にしたい(上げたい)
let pos = (view.frame.size.height / 8.0) * -1
label.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: pos).isActive = true
// 大本のViewと幅合わせ。view比60%で設定
label.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.6).isActive = true
// 大本のViewと高さ合わせ。view比8%で設定
label.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.08).isActive = true
- ラベル等の生成
- フォント等の設定
- Viewに登録
- translatesAutoresizingMaskIntoConstraintsをfalse
- Constraintsの設定
の順番で。
Viewに登録してからConstraintsを設定しないと落ちますし、translatesAutoresizingMaskIntoConstraintsフラグがデフォルトのtrueのままだと競合して表示できません。
なんでエラーが出るの?Constraints揃ってない??とか小一時間悩みました。
translatesAutoresizingMaskIntoConstraintsについてはViewの登録の前後どちらかでないと駄目なのかでどうかまでは見てません。
位置の設定で固定値を使いたくない
デバイスごとの位置調整の問題でViewやラベルのサイズなんかはViewとEqualHeightなんかを駆使してmultipliterで%指定したりするわけですが、leadingAnchor(左端)や、topAnchor(上端)を設定しようと思ってAutoLayoutのUIでやろうとすると固定値を入れる羽目になるわけで。
コードで打てばなんとかなるのかな、と思いましたが、viewのheightAnchorやwidthAnchorからすぐに値を取り出せなくて少し悩みました。
// 大本のViewとY軸中心合わせ.
// 1/2を3/8にしたい(上げたい)
let pos = (view.frame.size.height / 8.0) * -1
label.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: pos).isActive = true
上のソースのここでしれっとやってるのですが、
view.frame.size.heightでviewのフレームの高さの数値が取れるので、それで計算してしまえばいけます。widthもあるよ!
topAnchor、leadingAnchorの場合はこんな感じ、です。
// Viewの上端から10%の位置を指定
let posTop = view.frame.size.height * 0.1
label.topAnchor.constraint(equalTo: view.topAnchor, constant: posTop).isActive = true
// viewの幅の5%の位置を指定
let posLead = view.frame.size.width * 0.05
label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: posLead).isActive = true