この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
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 をチェックしてみてください!
本記事で扱ったサンプルコードは以下のリポジトリで公開しています。