この記事はXcode 4.6.* + iOS 6のものです。Xcode 5 + iOS 7はこちら。

http://blogios.stack3.net/archives/1488

前回の続き。今回はSubviewを横に並べて、かつ幅を自動調整するサンプルを説明したいと思います。

サンプル: https://github.com/stack3/STLayoutViewSample

サンプルのMenu画面のAuto LayoutセクションからHorizontalを選択します。ありがちなTextField + Button、Label + TextFieldの組み合わせです。

f:id:eimei23:20130103130057p:plain

横に回転するとTextFieldのみ幅が伸びます。

f:id:eimei23:20130103130109p:plain

Long Text Buttonを押すと今度はSearch ButtonとName Labelのテキストが変更されて幅が伸びます。

f:id:eimei23:20130103130119p:plain

このレイアウトを調整する部分は、プログラムを一切書いてません。Auto LayoutのConstraintだけで実現できているのです。素晴らしいですね!自分もこのサンプルが一番お気に入りだったりします(笑)sizeThatFitsメソッド地獄さようなら。

STAutoLayoutHorizontalViewController.xibを開きます。

f:id:eimei23:20130103130126p:plain

まずは一番上のTextFieldとSearch Buttonについて説明します。TextFieldを選択してConstraintを確認しましょう。

f:id:eimei23:20130103130133p:plain

Size InspectorからもConstraintを確認。

f:id:eimei23:20130103130140p:plain

  • Leading Space to: Superview – Superview左端との間隔固定
  • Top Space to: Superview – Superview上端との間隔固定
  • Align Baseline to: Button – Search – Search Buttonと垂直方向を揃える
  • Trailing Space to: Button – Search – Search Buttonとの水平方向間隔固定

それぞれのConstraintはこのようになります。大事なことはWidth Constraintがないことです。つまり横幅は自動調整されるということです。

次にSearch Buttonを選択してConstraintを確認しましょう。

f:id:eimei23:20130103130148p:plain

f:id:eimei23:20130103130154p:plain

  • Height Equals: 32 – 32pxに高さ固定
  • Bottom Space to: Text Field – 下にあるTextFieldとの幅固定
  • Trailing Space to: Superview – Superviewとの右端の間隔固定
  • Align Baseline to: Text Field – 左のTextFieldとの垂直方向を揃える
  • Leading Space to: Text Field – 左のTextFieldとの間隔固定
  • Top Space to: Superview – Superview上端との間隔固定

Search ButtomもText Field同様にWidth Constraintがないことに注目。つまり横幅は自動調整されます。

これらのConstraintにより、「TextFieldは幅自動調整、かつSuperviewとの上と左の間隔を固定、かつSearch Buttonとの間隔固定」「Search Buttonは幅自動調整、かつSuperviewとの上と右の間隔を固定」というAuto Layoutが実現されています。

次は実際にこれらのConstraintを設定するための手順を説明します。まずはText FieldとSearch Buttonを削除してください。

f:id:eimei23:20130103130200p:plain

そしてTextFieldを青い点線のガイドにそって配置します。

f:id:eimei23:20130103130206p:plain

次にButtonを配置しタイトルをSearchにして高さを32pxし青いガイドにそって配置。

f:id:eimei23:20130103130215p:plain

配置後はこのようになります。

f:id:eimei23:20130103130222p:plain

TextFieldの幅を伸ばしてSearch Buttonとの間隔を縮めます。この時もガイドに従いましょう。

f:id:eimei23:20130103130228p:plain

最終的にこういう感じになれば良いと思います。

f:id:eimei23:20130103130233p:plain

次にSearch ButtonとIBOutlet _searchButton変数とのリンクです。File’s Ownerを右クリックして黒いウィンドウを開き、_searchButtonの右横の丸から線を引っ張ってリンクします。これはAuto Layoutと関係無いですが、Long Text Buttonを押した時のタイトルを変更するのに必要です。

f:id:eimei23:20130103130240p:plain

とりあえず、この段階でSimulatorを起動してみましょう。そしてLong Text Buttonを押します。

f:id:eimei23:20130103130247p:plain

ボタンのタイトルがはみ出てしまいました・・・

画面を回転させるとTextFieldの幅は伸びていますね。

f:id:eimei23:20130103130255p:plain

Search Buttonの幅が自動調整されない理由はWidth Constraintがあるからです。Search Buttonを選択してSize Inspectorで確認してください。

f:id:eimei23:20130103130308p:plain

これを取り除きましょう。Search Buttonを選択してEditor > Size to Fit Contentを選択してください。

f:id:eimei23:20121231224113p:plain

f:id:eimei23:20130103131301p:plain

このようにボタンの高さが変わってしまいましたが、とりあえずこのままの状態で、Size Inspectorを見てましょう。

f:id:eimei23:20130103130329p:plain

Height Constraintは消えましたが、Width Constraintは残ったままです。TextFieldとの間隔とSuperview右端との間隔のConstraintがあるためか、幅は勝手に固定されてしまうようです。これを消すにはどうすればよいでしょうか。

Size InspectorのContent Hugging Priorityを250から251に変更してみてください。

f:id:eimei23:20130103130334p:plain

Width Constraintが消えましたね!このように他のConstraintとコンフリクトして、自動調整されないSubviewは、Content Hugging Priorityを上げてみるとよいでしょう。

高さは自動調整しないので元の32pxに位置を調整し直して完成です。

f:id:eimei23:20130103130341p:plain

この状態でSimulatorを起動し、Long Text Buttonを押すとButtonのタイトルに応じて自動調整されるようになっているはずです。

f:id:eimei23:20130103130119p:plain

まとめ

  • Subviewを横並びにして幅を自動調整する際には、それぞれWidth Constraintを持たない状態にする
  • Width Constraintが残る場合は、そのSubviewのContent Hugging Priorityを上げる

慣れるまでわかりづらいかもしれませんが、プログラムを書くより遥かに楽だと思います。ButtonやLabelの文字列は言語環境によって変わるため、Localization対応では気にするべきところです。隣接するSubviewどうしの幅が自動調整されるのは大変助かりますね。

次にName LabelとTextFieldについて説明しましょう。基本は先程のTextFieldとButtonの組み合わせと同じですので手短に説明します。

Name Labelを選択してConstraintを視覚的に確認。

f:id:eimei23:20130103163850p:plain

Size InspectorでConstraint確認。

f:id:eimei23:20130103164121p:plain

Width Constraintがないのでテキストが変わった時に幅が自動調整されます。他のConstraintについてはもう説明する必要はありませんね。あとはContent Hugging PriorityのHorizontalが+1され251にしていることに注目。こうしないとSearch Buttonの時と同じようにLong Text Buttonを押してLabelのテキストが変わった時に自動調整されなくなってしまいます。

TextFieldを選択してConstraintを確認。

f:id:eimei23:20130103163908p:plain

Size InspectorからもConstraintを確認。

f:id:eimei23:20130103163915p:plain

Width Constraintがないので横画面になった時に幅が自動調整されます。

一度Name LabelとTextFieldを削除して、自分で配置しなおしてみてください。そしてConstraintとContent Hugging Priorityを設定して、自動調整がうまくいくようにしてみましょう。

以上、Subviewを横並びに配置し、幅を自動調整する説明でした。次回はSubviewを縦並びに配置する方法について説明します。

その6へつづく