[iOS] Auto Layout の制約設定を楽にしてくれるライブラリ「Cartography」を試してみた #tryswiftconf
はじめに
try! Swift TOKYO 2017 の Sommer Panage さんの講演「UIをSwiftyに書く」で紹介されていたライブラリ「Cartography」が気になったので試してみました。
本記事では「Cartography」の使用方法や導入方法などを紹介していきます。
検証環境
- Xcode Version 8.2.1
- iPhone 7, iOS 10.2.1
Cartography
Auto Layout の制約を宣言的に設定できるライブラリです。
使用方法や NSLayoutConstraint を直接使用する場合との比較などについては後述します。
導入
CocoaPods を使用して導入できます。
use_frameworks! target 'CartographyDemos' do pod 'Cartography', '~> 1.0' end
NSLayoutConstraint を直接使用する場合との比較
以下のように固定サイズの View を中央に配置するレイアウトに関して、「NSLayoutConstraint を直接使用する場合」と「Cartography を使用する場合」の実装を比較してみます。
NSLayoutConstraint
を直接使用する
NSLayoutConstraint
のイニシャライザを使用する場合、制約を設定する実装は以下のようになります。
childView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint( item: childView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: 100.0 ).isActive = true NSLayoutConstraint( item: childView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: 100.0 ).isActive = true NSLayoutConstraint( item: childView, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1.0, constant: 0.0 ).isActive = true NSLayoutConstraint( item: childView, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1.0, constant: 0.0 ).isActive = true
Cartography を使用する
Cartography を使用する場合、constrain
関数を使用して以下のように実装できます。短くて読みやすいですね。
constrain(childView, view) { childView, view in childView.width == 100 childView.height == 100 childView.centerX == view.centerX childView.centerY == view.centerY }
その他の使用例
View のエッジに対する制約を設定する
View のエッジ同士に制約を設定したい場合に inset
関数を使用できます。
constrain(webView, view) { webView, view in webView.edges == inset(view.edges, 0.0, 0.0, 0.0, 0.0) }
画面いっぱいになるように WebView を配置したい場合などに使用できます。
View の Align と Distribute に関する制約を設定する
複数の View の端を揃えたい場合には align
関数を、
View 間に一定のスペースを設定したい場合には distribute
関数を使用できます。
constrain(view1, view2, view3, view) { view1, view2, view3, view in view2.center == view.center view2.height == 80.0 view2.width == 80.0 view1.size == view2.size view3.size == view2.size // Aligns align(top: view1, view2, view3) // Distributes distribute(by: 20.0, horizontally: view1, view2, view3) }
上記の実装によって、以下のスクショのレイアウトを実現できます。
制約を差し替える
ConstraintGroup
を使用して制約をキャプチャすることによって、制約を動的に差し替えることができます。
let constraintGroup = ConstraintGroup() // Attach `childView` to the middle left corner of its superview constrain(childView, replace: constraintGroup) { childView in childView.centerY == childView.superview!.centerY childView.left == childView.superview!.left } /* Later */ // Move the childView to the bottom right corner of its superview constrain(childView, replace: constraintGroup) { childView in childView.bottom == childView.superview!.bottom childView.right == childView.superview!.right } UIView.animate(withDuration: 0.5, animations: view.layoutIfNeeded)
上記の実装によって、以下のようなアニメーションを実現できます。
さいごに
本記事では、Auto Layout の制約を宣言的に設定できるライブラリ「Cartography」を紹介しました。
紹介していない機能が他にもありますので、気になった方は Cartography の README か Functions Reference をチェックしてみてください!
本記事で扱ったサンプルコードは以下のリポジトリで公開しています。