以前からAutolayoutの重要性や便利さをちらちら目にしてきましたがとっつきにくさからずっと避けてました。
そろそろ身につけなきゃとうことでレシピをまとめたいと思います。
参考
http://www.slideshare.net/classmethod/i-os-auto-layout
を参考にさせて頂きました。
Autolayoutとは
AutolayoutとはviewにConstraint(制約)を付けることでレイアウトする方法。
各view同士を5px間隔で配置する、など画面の大きさにとらわれず最適なviewの配置をします。
制約はNSLayoutConstraint
クラスによって定義でき、制約には優先度を設定できます。
NSLayoutConstraint
NSLayoutConstraint
は2つのコンストラクタがあります。
constraintsWithVisualFormat:options:metrics:views
こっちの方が複数のviewの制約を一度に定義できるので便利そう。
だが、visualFormat
の書き方がとっつきにくいのでAutolayoutについて理解が深まってから。
例えば@"V:|-8-[button1]"
みたいにV(縦)方向の定義で
「上8px隙間を開けてbutton1を配置する」といった具合。
今回はこちらは使わない
constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
こちらは1つのviewに対して制約を定義していく。
item
とtoItem
に対して制約を定義して他の引数で制約を調整する。
今回はこっちを使ってNSLayoutConstraintの使い方を学んでいく。
arg | description |
---|---|
item | 制約を追加するview、このviewに対して第2引数のattribute で指定した属性を反映させる |
attribute | 属性 |
relateBy | 計算式の関係性 |
toItem | 位置計算に使用するview |
attribute | 位置計算に使用する属性、値の取得元はtoItem
|
multiplier | 乗算値 |
constant | 定数値 |
制約
制約はNSLayoutConstraint
でview同士やviewに対して制約を生成して親viewにaddConstraints
していく。
viewController
に子viewのaView
があるとすると
self.view.addConstraints([
NSLayoutConstraint(
item: self.aView,
attribute: NSLayoutAttribute.Top,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Top,
multiplier: 1.0,
constant: 0
)]
)
のようにself.view
に子viewであるself.aView
についての制約を追加していく
制約を考える上で
制約とは計算式で表されているみたい。
例えば「view1の右端から右に10pxの位置にview2の左端が位置する」ってのを書きたいとき
view2.left = view1.right * 1 + 10
(item).(attribute1) (relatedBy) (toItem).(attribute2) * (multiplier) + (constant)
relatedBy
は=
を表す。NSLayoutRelation.Equal
みたいな。
となる。これを想像しながら制約を作っていくとイメージしやすそう
コードレシピ
コード書いてみないと覚えらんないので色んな制約を試してみました。
画面上部に引っ付いている、横幅いっぱいのnavigatoinView
self.navigationView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addConstraints([
// self.veiwの上から0pxの位置に配置
NSLayoutConstraint(
item: self.navigationView,
attribute: NSLayoutAttribute.Top,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Top,
multiplier: 1.0,
constant: 0
),
// self.viewの横幅いっぱいにする
NSLayoutConstraint(
item: self.navigationView,
attribute: NSLayoutAttribute.Width,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Width,
multiplier: 1.0,
constant: 0
),
// self.viewのレイアウトに関わらず高さは64px
NSLayoutConstraint(
item: self.navigationView,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
toItem: nil,
attribute: NSLayoutAttribute.Height,
multiplier: 1.0,
constant: 64
)]
)
navigationViewの上から10px左から10pxの位置にあり、縦横44pxのleftButton
self.leftButton.setTranslatesAutoresizingMaskIntoConstraints(false)
self.navigationView.addConstraints([
// 上から10px
NSLayoutConstraint(
item: self.leftButton,
attribute: .Top,
relatedBy: .Equal,
toItem: self.navigationView,
attribute: .Top,
multiplier: 1.0,
constant: 10
),
// 左から10px
NSLayoutConstraint(
item: self.leftButton,
attribute: .Left,
relatedBy: .Equal,
toItem: self.navigationView,
attribute: .Left,
multiplier: 1.0,
constant: 10
),
// 横(固定)
NSLayoutConstraint(
item: self.leftButton,
attribute: .Width,
relatedBy: .Equal,
toItem: nil,
attribute: .Width,
multiplier: 1.0,
constant: 44
),
// 縦(固定)
NSLayoutConstraint(
item: self.leftButton,
attribute: .Height,
relatedBy: .Equal,
toItem: nil,
attribute: .Height,
multiplier: 1.0,
constant: 44
)]
)
navigationViewの中央にある、横幅がnavigationViewの横幅によって動的に変化するcenterView
横幅320pxの時、navigationView.width:320px、centerView.width:100pxの比率を保ような横幅
self.centerView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.navigationView.addConstraints([
// centerViewのcenter.xをnavigationViewと同じに
NSLayoutConstraint(
item: self.centerView,
attribute: .CenterX,
relatedBy: .Equal,
toItem: self.navigationView,
attribute: .CenterX,
multiplier: 1.0,
constant: 0
),
// centerViewのcenter.yをnavigationViewと同じに
NSLayoutConstraint(
item: self.centerView,
attribute: .CenterY,
relatedBy: .Equal,
toItem: self.navigationView,
attribute: .CenterY,
multiplier: 1.0,
constant: 0
),
// navigationView.width:320のときcenterView:100の比率
NSLayoutConstraint(
item: self.centerView,
attribute: .Width,
relatedBy: .Equal,
toItem: self.navigationView,
attribute: .Width,
multiplier: 100.0 / 320.0,
constant: 0
),
// 縦は44pxで固定
NSLayoutConstraint(
item: self.centerView,
attribute: .Height,
relatedBy: .Equal,
toItem: nil,
attribute: .Height,
multiplier: 1.0,
constant: 44
)]
)
centerViewの右から20pxのところに位置する縦横44pxのrightButton
self.rightButton.setTranslatesAutoresizingMaskIntoConstraints(false)
self.navigationView.addConstraints([
// centerViewの右から20pxのところに配置
NSLayoutConstraint(
item: self.rightButton,
attribute: .Left,
relatedBy: .Equal,
toItem: self.centerView,
attribute: .Right,
multiplier: 1.0,
constant: 20
),
// center.yはcenterViewと同じ
NSLayoutConstraint(
item: self.rightButton,
attribute: .CenterY,
relatedBy: .Equal,
toItem: self.centerView,
attribute: .CenterY,
multiplier: 1.0,
constant: 0
),
// 横(固定)
NSLayoutConstraint(
item: self.rightButton,
attribute: .Width,
relatedBy: .Equal,
toItem: nil,
attribute: .Width,
multiplier: 1.0,
constant: 44
),
// 縦(固定)
NSLayoutConstraint(
item: self.rightButton,
attribute: .Height,
relatedBy: .Equal,
toItem: nil,
attribute: .Height,
multiplier: 1.0,
constant: 44
)]
)
おしまい
autolayoutの超基本を触れたのであとは深堀りをしていく。
このコードをロジックと同じクラスに書くと見通しが悪くなるのでレイアウトは別クラスにするとか設計を含めて学んでいきたい。
メモ
NSLayoutRelation
の種類別
NSLayoutAttribute
のLeftMargin
とか
優先度の使い方
constraintsWithVisualFormat:options:metrics:views
のこと