動的に生成されるViewに対して、marginなどを指定したいとき
Autolayoutをコードで書く必要があります。
ただ、普通に書くと..
addConstraint(NSLayoutConstraint(
item: button1,
attribute: .Right,
relatedBy: .Equal,
toItem: button2,
attribute: .Left,
multiplier: 1.0,
constant: -12.0
))
たかだか左右のmarginを書くだけでもこれだけのコード量を書かねば
ならず、直感的ではないです。
何かCSSのように、簡単に書ける方法がないか探したところ
2パターンの書き方がありました。
[パターン1]Cartographyを使う
Cartography というライブラリを使うと、
Swiftのクロージャを使って簡単にレイアウトが組めます。
例えば、上記の例だと
constrain(button1, button2) { button1, button2 in
button1.right == button2.left - 12
}
こんなに簡単に書けます。(公式サイトの例を抜粋)
第1引数にレイアウトを指定したいView、第2引数に相対関係にあるViewを指定します。
更に簡略化して、こう書けます。
// swiftのクロージャーには略式の引数($0, $1..)が予め設定されている。inも要らなくなる
constrain(button1, button2) {
$0.right == $1.left - 12
}
実際に使ってみた
親Viewの内側にいい感じにUILabelをレイアウトしたい
constrain(footerLabel, containerView) {
$0.edges == inset($1.edges, 7, 16, 0, 16) // 左から、top, leading, bottom, trailing のmarginを指定
}
高さを指定
constrain(view) {
view.width == 100 // 幅に変更がなくても、指定しないと通常のAutolayout同様エラーで表示されない
view.height == 200
}
めちゃ便利です。
[パターン2]NSLayoutAnchorを使う
iOS9以上であれば、NSLayoutAnchorというクラスを使えば、簡潔にAutolayoutが書けます。
こちらも実際に使ってみました。
親Viewにピッタリフィットした、WKWebView
(WKWebViewはStoryBoardに置けるUIパーツがないので、Autolayoutをコードで指定する必要がある)
// 上辺の制約
webview.topAnchor.constraintEqualToAnchor(containerView.topAnchor, constant: 0.0).active = true
// 下辺の制約
webview.bottomAnchor.constraintEqualToAnchor(containerView.bottomAnchor, constant: 0.0).active = true
// 左辺の制約
webview.leadingAnchor.constraintEqualToAnchor(containerView.leadingAnchor, constant: 0.0).active = true
// 右辺の制約
webview.trailingAnchor.constraintEqualToAnchor(containerView.trailingAnchor, constant: 0.0).active = true
簡単!!
どっちを採用する?
NSLayoutAnchorはiOS9~なので、iOS8の対応が必要な場合は、
iOS8対応もしている、Cartography一択。
iOS9以上が対象であっても、個人的にはCartographyのほうが未だシンプルなので、
採用するかと思います。
参考サイト
Cartography
[iOS 9] NSLayoutAnchorを使ってNSLayoutConstraintを簡潔に書こう!