71
iOS6 Auto Layout 2012/12/10 ククククククク クククク

iOS6 Auto Layout

  • View
    16.051

  • Download
    1

Embed Size (px)

Citation preview

Page 1: iOS6 Auto Layout

iOS6 Auto Layout

2012/12/10クラスメソッド かけがわ

Page 2: iOS6 Auto Layout

自己紹介

Page 3: iOS6 Auto Layout

アジェンダ• Auto Layout• Auto Layout の基礎知識• Interface Builder で Auto Layout を設定• ソースコードで Auto Layout を設定• Auto Layout 補足

Page 4: iOS6 Auto Layout

Auto Layout の基礎知識

Page 5: iOS6 Auto Layout

Auto Layout

• 「制約」ベースのレイアウトシステム

• Autosizing を置き換えるもの

• Mac アプリケーションでは、 OS X Lion で既に導入されている

Page 6: iOS6 Auto Layout

Constraint

• レイアウトを決定するための「制約」

• 他の UI コンポーネントとの相対的な位置・サイズを定義

• 制約は NSLayoutConstraint クラスのインスタンスによって表現される

Page 7: iOS6 Auto Layout

Auto Layout と Autosizing の違いAutosizing

• サブビューの親ビューに対する相対関係を指定する• 親ビューとの間のマージン• 親ビューに追従してリサイズするか

Page 8: iOS6 Auto Layout

Auto Layout と Autosizing の違いAuto Layout

• レイアウト上のルールを制約として定義• サブビューの親ビューに対する相対位置• 兄弟ビューとの相対位置やサイズ• 自身のサイズ

• ルールは必ずしも厳密に満たされない• サイズや位置に関して、「 20px 以上」や

「 10px 以下」といった表現が可能• 優先順位

Page 9: iOS6 Auto Layout

Leading & Trailing• アラビア語など、右側が文頭になる環境に対する、レイアウト上の

ローカライズを容易にするための機能

• Leading は文字列の先頭側、 Trailing は文字列の末尾側を指す

• 日本語や英語の環境では、 Leading は Left 、 Trailing は Right に対応する

• アラビア語など、右側が文頭になる環境では、 Leading がRight 、 Trailing が Left に対応する

• Left や Right の代わりに Leading や Trailing を利用しておくと、 OS の言語がアラビア語に設定されている環境ではレイアウトの位置が左右反転する

Page 10: iOS6 Auto Layout

Leading & Trailing

OS の言語設定がアラビア語OS の言語設定が英語

親ビュー内でのボタンの水平方向のアライメントに関して、 Leading 側に寄せて 20px のスペースを置くという制約を追加した場合

Page 11: iOS6 Auto Layout

Auto Layout の使い方

Page 12: iOS6 Auto Layout

使い方使い方は2通り

• Interface Builder 上で制約を設定する• ソースコードで NSLayoutConstraint クラス

を使って設定する

Page 13: iOS6 Auto Layout

Interface Builder で制約を設定する

Page 14: iOS6 Auto Layout

Auto Layout の切り替え• ファイルインスペクタの Use

Autolayout を有効にする

• Use Autolayout を無効にすれば従来通り

• iOS5.x 以前で Use Autolayout を有効にするとクラッシュするので注意

Page 15: iOS6 Auto Layout

Interface Builder 上のメニュー

Page 16: iOS6 Auto Layout

Interface Builder 上のメニュー

Page 17: iOS6 Auto Layout

Interface Builder 上のメニュー

コンポーネントのアライメントに関する制約を追加する操作

Page 18: iOS6 Auto Layout

Interface Builder 上のメニュー

コンポーネントの相対的な位置やサイズを固定する制約を追加する操作

Page 19: iOS6 Auto Layout

Interface Builder 上のメニュー

Interface Builder 上でコンポーネントをリサイズした場合に、周辺コンポーネントに既存の制約を適用して移動やリサイズなどを行うかを設定する

• Siblings and Ancestors親と兄弟に制約を適用する

• Descendants子に制約を適用する

Page 20: iOS6 Auto Layout

Align – 端揃え• Left Edges

• 複数のコンポーネントの左端の水平位置を揃える制約を追加する• 追加される制約は Direction の設定による

• Right Edges• 複数のコンポーネントの右端の水平位置を揃える制約を追加する• 追加される制約は Direction の設定による

• Top Edges• 複数のコンポーネントの上端の垂直位置を揃える制約を追加する• 追加される制約は Top Alignment

• Bottom Edges• 複数のコンポーネントの下端の垂直位置を揃える制約を追加する• 追加される制約は Bottom Alignment

Page 21: iOS6 Auto Layout

Align – 基準位置揃え• Horizontal Centers

• 複数のコンポーネントの水平方向の中心位置を揃える制約を追加する

• 追加される制約は Center X Alignment

• Vertical Centers• 複数のコンポーネントの垂直方向の中心位置を揃える制約を追加す

る• 追加される制約は Center Y Alignment

• Baselines• 複数のコンポーネントのベースライン位置関係を固定する制約を追

加する• 追加される制約は Baseline Alignment

Page 22: iOS6 Auto Layout

Align – 親ビュー内でセンタリング

• Horizontal Center in Container• コンポーネントとその親コンテナの水平方向の中心位置

を揃える制約を追加する• 追加される制約は Center X Alignment

• Vertical Center in Container• コンポーネントとその親コンテナの垂直方向の中心位置

を揃える制約を追加する• 追加される制約は Center Y Alignment

Page 23: iOS6 Auto Layout

Pin – サイズ• Width

• コンポーネントの幅に関する制約を追加する• 追加される制約は Width• 制約は対象コンポーネントに追加

• Height• コンポーネントの高さに関する制約を追加する• 追加される制約は Height• 制約は対象コンポーネントに追加

Page 24: iOS6 Auto Layout

Pin – コンポーネント間の間隔• Horizontal Spacing

• 2つのコンポーネントの間の水平方向の距離に関する制約を追加する

• 追加される制約は Horizontal Space

• Vertical Spacing• 2つのコンポーネントの間の垂直方向の距離に関する制約

を追加する• 追加される制約は Vertical Space

Page 25: iOS6 Auto Layout

Pin – 親ビューの端との間隔• Leading Space to SuperView

• コンポーネントの左端とその親ビューの左端の距離に関する制約を追加する• 追加される制約は Horizontal Space

• Trailing Space to SuperView• コンポーネントの右端とその親ビューの右端の距離に関する制約を追加する• 追加される制約は Horizontal Space

• Top Space to SuperView• コンポーネントの上端とその親ビューの上端の距離に関する制約を追加する• 追加される制約は Vertical Space

• Bottom Space to SuperView• コンポーネントの下端とその親ビューの下端の距離に関する制約を追加する• 追加される制約は Vertical Space

Page 26: iOS6 Auto Layout

Pin – サイズの連動• Widths Equally

• 複数のコンポーネントの幅を等しくする制約を追加する• 追加される制約は Equal Widths

• Heights Equally• 複数のコンポーネントの高さを等しくする制約を追加す

る• 追加される制約は Equal Heights

Page 27: iOS6 Auto Layout

Demo

Page 28: iOS6 Auto Layout

制約の種類• アライメントに関する制約(7種類)

Leading(Left or Right) Alignment, Trailing(Right or Left) Alignment, Center X AlignmentTop Alignment, Bottom Alignment, Center Y Alignment, Baseline Alignment

• 相対位置に関する制約(2種類)Horizontal SpaceVertical Space

• サイズに関する制約(2種類)Width, Height

• サイズの連動に関する制約(2種類)Equal Widths, Equal Heights

Page 29: iOS6 Auto Layout

制約の種類• アライメントに関する制約(7種類)

Leading(Left or Right) Alignment, Trailing(Right or Left) Alignment, Center X AlignmentTop Alignment, Bottom Alignment, Center Y Alignment, Baseline Alignment

• 相対位置に関する制約(2種類)Horizontal SpaceVertical Space

• サイズに関する制約(2種類)Width, Height

• サイズの連動に関する制約(2種類)Equal Widths, Equal Heights

実際に追加される制約は13種類

Page 30: iOS6 Auto Layout

制約の種類• アライメントに関する制約(7種類)

Leading(Left or Right) Alignment, Trailing(Right or Left) Alignment, Center X AlignmentTop Alignment, Bottom Alignment, Center Y Alignment, Baseline Alignment

• 相対位置に関する制約(2種類)Horizontal SpaceVertical Space

• サイズに関する制約(2種類)Width, Height

• サイズの連動に関する制約(2種類)Equal Widths, Equal Heights

実際に追加される制約は13種類大きく分類すると4種類

Page 31: iOS6 Auto Layout

制約の種類• Interface Builder 上から実行できる制約追加のコマンド

は 19 種類

• でも実際には、制約の種類と制約の適用対象のバリエーションの組み合わせで Interface Builder のコマンドの種類が多くなっているだけ

• 制約の適用対象のバリエーション• 親ビューとその子コンポーネント• 兄弟コンポーネント同士• 対象コンポーネントのみ

Page 32: iOS6 Auto Layout

User Constraint• Interface Builder 上で設定される制約には

2種類あり、アイコンの色が異なっている

• 青いアイコンはユーザー編集可能な制約を表す( User Constraint )キャンバス上の制約インジケーターが太い

• 紫のアイコンは Interface Builder が自動的に挿入した制約キャンバス上の制約インジケーターが細い

Page 33: iOS6 Auto Layout

User Constraint

• User Constraint はシーンやキャンバス、サイズインスペクタから削除することができる

• Interface Builder が追加した制約は、サイズインスペクタの Constraints で対象の制約を選び、 Promote to User Constraint を選択すると User Constraint にすることができる

Page 34: iOS6 Auto Layout

IB で Auto Layout を利用するとよくわからない動きをする・・・

• Auto Layout は実行時にレイアウトを決定するのに十分な制約を設定する必要がある

• 必要となる制約が不足している場合、 Interface Builder が制約を自動で設定する• このため、制約を編集すると既存の制約が壊

されるように感じる

Page 35: iOS6 Auto Layout

IB で Auto Layout を利用する際のポイント

• 自動設定された制約(紫アイコン)とユーザー設定の制約(青アイコン)を意識すると思い通りに設定できる

• 実体である NSLayoutConstraint を意識する

Page 36: iOS6 Auto Layout

NSLayoutConstraint で制約を設定する

Page 37: iOS6 Auto Layout

NSLayoutConstraint

• レイアウトの制約を表すクラス

• 基本的にイミュータブルなので、制約を変更する際は新しいインスタンスを作成して差し替える

Page 38: iOS6 Auto Layout

NSLayoutConstraint の計算式

属性値 1 == 属性値 2 * 乗数 + 定数

Page 39: iOS6 Auto Layout

NSLayoutConstraint• id firstItem

• 属性値の計算結果を反映するオブジェクト

• NSLayoutAttribute firstAttribute• 計算結果を反映する属性• firstItem で指定されたオブジェクトに対して、この属性に対応する値を属性値

として反映する

• id secondItem• 計算式に利用する属性値を取得するオブジェクト

• NSLayoutAttribute secondAttribute• 計算式に利用する属性• 属性値の取得元は secondItem で指定されたオブジェクト

Page 40: iOS6 Auto Layout

NSLayoutConstraint• id firstItem

• 属性値の計算結果を反映するオブジェクト

• NSLayoutAttribute firstAttribute• 計算結果を反映する属性• firstItem で指定されたオブジェクトに対して、この属性に対応する値を属性値

として反映する

• id secondItem• 計算式に利用する属性値を取得するオブジェクト

• NSLayoutAttribute secondAttribute• 計算式に利用する属性• 属性値の取得元は secondItem で指定されたオブジェクト

firstItem は計算結果を反映する側secondItem は計算式に値を利用する側

Page 41: iOS6 Auto Layout

NSLayoutConstraint• CGFloat constant

• 計算式の中で属性値の算出に利用する定数値• この値だけは、例外的に NSLayoutConstraint のインスタンス化後に変更できる

• CGFloat multiplier• 計算式の中で属性値の算出に利用する乗算値• 属性値同士の比率を定義するのに使用する• 今のところ乗算値を利用した制約の定義は Interface Builder でサポートされて

いない

• NSLayoutPriority priority• 制約の優先順位

• NSLayoutRelation relation• 計算式とその計算結果の関係性を指定する

Page 42: iOS6 Auto Layout

NSLayoutAttribute

• 制約の対象となる属性を表す列挙型

• ボタン1の「下端」から 10px 下側に、ボタン2の「上端」がくるよう配置する制約の場合• ボタン1の属性は NSLayoutAttributeBottom• ボタン2の属性は NSLayoutAttributeTop

Page 43: iOS6 Auto Layout

NSLayoutAttributetypedef NS_ENUM(NSInteger, NSLayoutAttribute) { NSLayoutAttributeLeft = 1, NSLayoutAttributeRight, NSLayoutAttributeTop, NSLayoutAttributeBottom, NSLayoutAttributeLeading, NSLayoutAttributeTrailing, NSLayoutAttributeWidth, NSLayoutAttributeHeight, NSLayoutAttributeCenterX, NSLayoutAttributeCenterY, NSLayoutAttributeBaseline, NSLayoutAttributeNotAnAttribute = 0};

Page 44: iOS6 Auto Layout

NSLayoutRelation

• 計算式とその計算結果の関係性を表す列挙型

• 「等しい」「以上」「以下」の3つ

typedef NS_ENUM(NSInteger, NSLayoutRelation) { NSLayoutRelationLessThanOrEqual = -1, NSLayoutRelationEqual = 0, NSLayoutRelationGreaterThanOrEqual = 1,};

Page 45: iOS6 Auto Layout

NSLayoutPriority• 競合する制約間の優先順位を表す値

• この値が高い制約から優先的に制約で定義された条件が満たされていく

• 1 から 1000までの CGFloat値

• いくつかの定数値が UILayoutPriority 列挙型として用意されているので、基本的にこの値を利用するのがよさそう

enum { UILayoutPriorityRequired = 1000, UILayoutPriorityDefaultHigh = 750, UILayoutPriorityDefaultLow = 250, UILayoutPriorityFittingSizeLevel = 50};typedef float UILayoutPriority;

Page 46: iOS6 Auto Layout

NSLayoutConstraint の計算式

属性値 1 == 属性値 2 * 乗数 + 定数

Page 47: iOS6 Auto Layout

NSLayoutConstraint の計算式

属性値 1 == 属性値 2 * 乗数 + 定数

firstItemfirstAttribute

secondItemsecondAttribute

multiplier

constant

relation

Page 48: iOS6 Auto Layout

NSLayoutConstraint の計算式• ボタン1の右端から右に 10px の位置にボタン2の左端が位置

する場合

button2.left == button1.right * 1 + 10

• ビュー2の幅がビュー1の幅の3倍の場合

view2.width == view1.width * 3 + 0

Page 49: iOS6 Auto Layout

NSLayoutConstraint の計算式• ボタン1の右端から右に 10px の位置にボタン2の左端が位置

する場合

button2.left == button1.right * 1 + 10

• ビュー2の幅がビュー1の幅の3倍の場合

view2.width == view1.width * 3 + 0

すべての制約は計算式で表現される

Page 50: iOS6 Auto Layout

NSLayoutConstraint の作成

[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view1]-|" options:0 metrics:nil views:views];

• Visual Format Language を利用する方法

[NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeHeight multiplier:2.0f constant:0.0f];

• Visual Format Language を利用しない方法

Page 51: iOS6 Auto Layout

Visual Format Language

• 制約を NSString で表現する DSL のようなもの

@"V:|-[view1]-20-[view2]-|”

Page 52: iOS6 Auto Layout

Visual Format Language

• 制約を NSString で表現する DSL のようなもの

@"V:|-[view1]-20-[view2]-|”

"V:"垂直方向のレイアウト

"|"親ビューの

エッジ

“[view2]"コンポーネントのインスタンス

"-20-"20px のスペース

"-"スペース

(デフォルト値)

Page 53: iOS6 Auto Layout

Visual Format Language

• 制約を NSString で表現する DSL のようなもの

@"V:|-[view1]-20-[view2]-|”

以下の3つの制約を表現している・垂直方向において、 view1 の上端は親ビューの上端からデフォルト値( 20px )下にある・垂直方向において、 view1 の下端と view2 の上端は 20px 離れている・垂直方向において、 view2 の下端は親ビューの下端からデフォルト値( 20px )上にある

Page 54: iOS6 Auto Layout

Visual Format Language

• 文字列なのでコンパイラによるチェックはない

• 実行時にパースできないとエラーが発生する

• 詳細は Apple の公式ドキュメントを参照

Visual Format Languagehttps://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/AutolayoutPG/Articles/formatLanguage.html

Page 55: iOS6 Auto Layout

Demo

Page 56: iOS6 Auto Layout

コードNSDictionary *views = NSDictionaryOfVariableBindings(view1, view2);

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view1]-|" options:0 metrics:nil views:views]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view1]-20-[view2]-|" options:NSLayoutFormatAlignAllCenterX metrics:nil views:views]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view1(==view2)]" options:0 metrics:nil views:views]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeHeight multiplier:2.0f constant:0.0f]];

Page 57: iOS6 Auto Layout

Auto Layout 補足

Page 58: iOS6 Auto Layout

Intrinsic Content Size• 一部の UI コンポーネントは自身の推奨サイズを、 UIView で定義

された intrinsicConstentSize メソッドから取得できる

• UIButton, UILabel などが推奨サイズを持っている

• ラベルのみの UIButton であれば、内部のテキストの幅・高さにパディングを加えたものが推奨サイズとなる

• 内部のコンテンツの大きさが変化すると、推奨サイズも変化する

• Auto Layout においては、幅や高さを決定する制約が不足している場合に推奨サイズが使用される

Page 59: iOS6 Auto Layout

推奨サイズを持たない場合

Center X Alignment

Vertical Space (148)

Vertical Space (149)

Horizontal Space (36)

Page 60: iOS6 Auto Layout

推奨サイズを持つ場合

Center X Alignment

Vertical Space (148)

Page 61: iOS6 Auto Layout

推奨サイズを持つ場合

Center X Alignment

Vertical Space (148)

ボタンの幅と高さは推奨サイズが採用されるので、制約を追加する必要なし

Page 62: iOS6 Auto Layout

推奨サイズの優先順位• まわりのコンポーネントの制約によっては、推奨サイズを実現できないときがある

• 制約同士が競合した場合と同じように、推奨サイズも優先順位がつけられて実際のレイアウトに適用される• Content Hugging Priority• Content Compression Resistance Priority

Page 63: iOS6 Auto Layout

Content Hugging Priority

• UI コンポーネントのサイズが制約によって推奨サイズより大きくなる場合の「大きくなりにくさ」を決定する

• 実際には NSLayoutPriority の値で制約間での優先順位を設定している

• デフォルト値は UILayoutPriorityDefaultLow

• UIView にメソッドが用意されている– contentHuggingPriorityForAxis:– setContentHuggingPriority:forAxis:

Page 64: iOS6 Auto Layout

Content Compression Resistance Priority

• UI コンポーネントのサイズが制約によって推奨サイズより小さくなる場合の「小さくなりにくさ」を決定する

• Content Hugging Priority 同様、実際には優先順位の値が設定される

• デフォルト値は UILayoutPriorityDefaultHigh

• UIView にメソッドが用意されている– contentCompressionResistancePriorityForAxis:– setContentCompressionResistancePriority:forAxis:

Page 65: iOS6 Auto Layout

動的なレイアウトへの対応• ビューのプロパティが変更された場合など

に、動的にレイアウトを変更したい

• 今までは layoutSubviews をオーバーライドしてレイアウト処理を書いていた

• 制約を利用する場合も、同じように UIViewに制約変更用のライフサイクルメソッドが用意されている

Page 66: iOS6 Auto Layout

動的なレイアウトへの対応- updateConstraints

• オーバーライドして制約の更新処理を記述する• layoutSubviews と同じく、システムによって呼ばれるので自

分で呼び出さない• このメソッドをオーバーライドする場合は、 layoutSubviews

によるレイアウト処理はオーバーライドしないこと• 逆に layoutSubviews をオーバーライドする場合

は、 updateConstraint はオーバーライドしない

- setNeedsUpdateConstraints• updateConstraints の実行をトリガする• layoutSubviews に対する setNeedsLayout と同じ

Page 67: iOS6 Auto Layout

Auto Layout のデバッグUIView の UIConstraintBasedLayoutDebugging カテゴリに定義されているデバッグ用のメソッドを利用する

• - (NSArray *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis縦軸・横軸のそれぞれについて、現在適用されている制約を返すUILayoutConstraintAxis で制約を取得したい軸を指定する

• - (BOOL)hasAmbiguousLayout制約が不足してレイアウトが決定できない箇所がある場合 YES を返す

• - (void)exerciseAmbiguityInLayouthasAmbiguousLayout が YES の場合、可能性のあるレイアウトをランダムで画面に適用するリリースビルド作成の際は必ずこれらのメソッドは外すこ

と!

Page 68: iOS6 Auto Layout

Demo

Page 69: iOS6 Auto Layout

Auto Layout のメリット• より柔軟なレイアウトを frame を操作せず

に実現できる

• 込み入ったレイアウトを宣言的にプログラミングすることができる

• Visual Format Language による定義が手軽

Page 70: iOS6 Auto Layout

Auto Layout のデメリット• 学習コストが低いとは言えない

• シンプルなレイアウトを組むの場合はAutoResizingMask を使う方が手軽

• iOS5 では使えない

Page 71: iOS6 Auto Layout

ご清聴ありがとうございました