× [PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。 |
今やiOSでは当たり前となったAutoLayout。
制約(NSLayoutConstraint)を適切に指定することで、レイアウトを指定することができ、画面サイズの違う端末でも意図通りに表示できるようになる。 AutoLayoutによる位置・サイズの決定は、viewWillAppearとviewDidAppearの間で行われる。 【画面初期化の流れ】 viewDidLoad実行 ↓ viewWillAppear実行 ↓ AutoLayout実行(内部) ↓ ビューのlayoutSubviews実行 ↓ viewDidLayoutSubviews実行(もう一度呼ばれる) ↓ 画面が構成される(内部) ↓ 画面遷移開始(ここからユーザの眼に触れる) ↓ 画面遷移終了 ↓ viewDidAppear実行 間違って(あるいは面倒くさがって)ビューコントローラ上のコードで画面レイアウトを作ろうとして、画面表示前(viewDidLoadなど)でビューのframeを直接いじっても、 その後にAutoLayout制約が適用されて上書きされてしまう。 (じゃあviewDidAppearの後にframeをいじろう、と考えたくなるところだが、それだとちょっと間に合わない。画面遷移をしながら表示するビューの場合、frameをいじる前のビューが画面に映ってしまう(=手遅れ)なのだ。 だから、レイアウトを処理・変更する必要があるビューは、必ずカスタム定義をして layoutSubviews メソッドを実装しておく必要がある。 このメソッドは、viewWillAppearの後に呼ばれる。 また、画面を再構成する必要があると自動的に判断されたときにも呼ばれるし、明示的に呼びたい場合は、ビューコントローラで [view setNeedsLayout]; を実行すればよい。 じゃあどうするか。 制約適用直後に画面が映ってしまうのはさけられない。 ということはつまり、制約適用時に求める画面が構成されるようにしておけばいい。 だから、、、 【制約を動的に作成する】 ということになる。 つまり、AutoLayoutを使うようになった時点で、画面構成はすべて制約で作るようにするべきなのだ。 frameとかboundsとかを直接いじることはなくなってくるはずだ(少なくとも、定数値を代入するようなことはないはずだ。せっかくAutoLayoutを指定していても台無しになる)。 さて、そうすると、どうやってコード上で制約を記述するのか、ということを覚えなければならない。ストーリーボードではいつも作ってるけど、コーディングはどうやって…? 公式のAutoLayoutマニュアル 制約クラスは NSLayoutConstraint 制約のインスタンスを作るメソッドは2種類ある 1.constraintsWithVisualFormat: options: metrics: views: VisualFormat VisualFormatとは、制約を人間に見やすく記述できるDSL。 これを使用して、ビューのサイズや位置を指定する。storyboardとほぼ同じことができる 公式のVisual Format Language仕様 いくつか例示する。 なお、view1,view2などは、制約を作りたいビューのメンバ変数名(詳細は後述) view1の横幅を10にする H:[view1(==10)] view1の高さを20以上にする V:[view1(>=20)] view1の高さを20以上100以下にする V:[view1(>=20,<=100)] view1とview2の幅を同じにする H:[view1(==view2)] ※比較演算子は、==,>=,<= の3つしか使えない ※カッコで囲わないと、パーサーがビュー名の区切りを判断できない。 ※HもVも書かないときはH(水平方向)になる view1とview2を12px空けて横に並べる H:[view1]-12-[view2] view1とview2をデフォルトの間隔を空けて縦に並べる V:[view1]-[view2] view1とview2を間隔無しで並べる H:[view1][view2] superviewとの間隔を指定する。パイプ(|)がsuperviewを表す H:|-50-[view1]-50-| options 指定できる内容は以下 NSLayoutFormatAlignAllLeft NSLayoutFormatAlignAllRight NSLayoutFormatAlignAllTop NSLayoutFormatAlignAllBottom NSLayoutFormatAlignAllLeading NSLayoutFormatAlignAllTrailing NSLayoutFormatAlignAllCenterX NSLayoutFormatAlignAllCenterY NSLayoutFormatAlignAllBaseline NSLayoutFormatAlignAllLastBaseline NSLayoutFormatAlignAllFirstBaseline NSLayoutFormatDirectionLeadingToTrailing NSLayoutFormatDirectionLeftToRight NSLayoutFormatDirectionRightToLeft 何もいらなければ0を指定。 metrics 調べてない views VisualFormat内に登場したビュー名と、ビューへの参照を格納したNSDictionary。 上記の例だと、 NSDictionary viewsDictionary = [[NSDictionary alloc]initWithObjects:@[view1,view2] forKeys:@[@"view1",@"view2"]]; のような感じ。 ちなみにこれと同じことが NSDictionaryOfVariableBindings(view1, view2); と書くことができる。 戻り値 記述した制約をすべて満たせるNSLayoutConstraintの配列が返ってくる。 最終的なコード例 view1の横幅を40にし、view2を水平に12px空けて並べ、それぞれsuperviewと左右端を合わせる。(制約が4つ作られる)
例外を捕まえる VisualFormatは実行時にパースされるので、書き間違えていると例外が飛んでくる。 ちゃんとキャッチしてチェックしよう。
2.constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: item 制約を付けるビュー。 attribute 以下のものがある。 実態は前のメソッドのoptionに指定するNSLayoutFormat***と同じ。 NSLayoutAttributeLeft = 1, NSLayoutAttributeRight, NSLayoutAttributeTop, NSLayoutAttributeBottom, NSLayoutAttributeLeading, NSLayoutAttributeTrailing, NSLayoutAttributeWidth, NSLayoutAttributeHeight, NSLayoutAttributeCenterX, NSLayoutAttributeCenterY, NSLayoutAttributeBaseline, NSLayoutAttributeLastBaseline = NSLayoutAttributeBaseline, NSLayoutAttributeFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0), relatedBy 比較演算子。以下の3つ NSLayoutRelationLessThanOrEqual = -1, NSLayoutRelationEqual = 0, NSLayoutRelationGreaterThanOrEqual = 1, toItem 対象となるビューを指定する。 align系なら、どのビューからの距離か、を指定するときに使う。 size系なら、あのビューのサイズの○倍、というような指定の時に使う。 不要ならnilを指定。 attribute toItem側のattribute。 itemのtopとtoItemのtopが○○px離れてる、というような制約のときに使用。 なければ0。 multiplier 係数。計算式に使う。後述 constant 定数。計算式に使う。後述 コード例 view1の高さを123にする場合。
view1の上端をview2の上端から25px以上空ける制約
view1の幅をview2の高さの2倍より10大きいサイズにする制約
PR |
|