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

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

前回は各種Constraintの設定方法について説明しました。今回は実践的な内容にしたがってConstraintについて説明したいと思います。

サンプルを用意しましたので、まずはダウンロードしてください。

https://github.com/stack3/STLayoutViewSample

サイズ自動調整

サンプルのMenu画面からAuto LayoutセクションのSize to Fitを選択します。

f:id:eimei23:20130102091104p:plain

Flexible WidthとFlexible HeightというLabelが並んでいます。Long Textボタンを押してみましょう。以下のようになるはずです。

f:id:eimei23:20130102091117p:plain

LabelのサイズはAuto Layoutによる自動調整です。プログラムでsizeToFitメソッドの呼び出しなどはしていません。

XcodeからSTAutoLayoutSizeToFitController.xibを開いてください。

f:id:eimei23:20130101114856p:plain

Flexible Widthを選択し、Size InspectorからConstraintを見てみましょう。

f:id:eimei23:20130101114907p:plain

f:id:eimei23:20130101114918p:plain

上端と左端からの間隔を示すTop Space to SuperviewとLeading Space to SuperviewというConstraintはありますが、サイズを自動調整するようなConstraintはありません。(Bottom Space to…というConstraintは今回無視してください)

注意すべきなのはサイズの自動調整はConstraintではないということです。LabelやButtonはデフォルトでサイズ自動調整なのです。

次にサイズを固定する場合について説明します。Flexible Widthを選択してドラッグして幅を160pxほどにしましょう。

f:id:eimei23:20130101114936p:plain

そしてSize Inspectorを見るとWidth Equals: 160というConstraintが追加されているのを確認できます。

f:id:eimei23:20130101114954p:plain

WidthというConstraintは幅を固定するためのものです。

さてWidth Constraintを設定した状態でSimulatorを起動して、Long Textボタンを押してみましょう。

f:id:eimei23:20130102091130p:plain

このようになり末端が省略され自動調整されません。Width Constraintが働いて幅を固定するようになったからです。

サイズ自動調整に戻す場は、Flexible Widthを選択して、EditorメニューからSize to Fit Contentを選択します。

f:id:eimei23:20121231224113p:plain

その後、Size Inspectorを見るとWidth Constraintが消えているはずです。

f:id:eimei23:20130101114907p:plain

f:id:eimei23:20130101114918p:plain

この状態でもう一度Simulatorを起動して、Long Textボタンを押してみましょう。元通りサイズが自動調整されるはずです。

f:id:eimei23:20130102091117p:plain

複数行テキスト自動調整

次にFlexible Heightを選択してみましょう。

f:id:eimei23:20130101132239p:plain

Size InspectorにWidthやHeightのConstraintがないことを確認します。

f:id:eimei23:20130101132256p:plain

以下はLong Text Buttonとの間隔を示すConstraintです。

f:id:eimei23:20130101132305p:plain

Size InspectorのBottom Space to: Button – Long Textがこれに相当します。

f:id:eimei23:20130101132319p:plain

次に右端の間隔を示すConstraintを確認してみます。

f:id:eimei23:20130101132329p:plain

Size InspectorのTrailing Space to: Superviewがこれに相当します。

f:id:eimei23:20130101132338p:plain

また複数行表示するのでLabelのプロパティを以下のようにしてあります。

f:id:eimei23:20130101132346p:plain

これらのConstraintとLabelプロパティの組みわせにより、Flexible Heightは、

「複数行、かつサイズ自動調整、かつ右端のマージンを固定、かつLong Text Buttonとの間隔を固定する」

というAuto Layoutが実現されています。

Long Textボタンを押して複数行になったときに、Flexible Heightとの間隔を守りつつ、Long Textボタンが下に移動する部分も自動で行われています。プログラムは書いていないのです。素晴らしいですね!

さて、このサンプルではあらかじめConstraintが設定された状態なので、実際にどのようにConstraintを設定していくのかを説明します。

Flexible HeightとLong Text Buttonを削除しましょう。

f:id:eimei23:20130101132444p:plain

LabelをFlexible Widthの下に配置します。

f:id:eimei23:20130101132454p:plain

LabelのTextプロパティを”Flexible Height”に変更します。また複数行にするためにLinesとLine Beaksも設定します。

f:id:eimei23:20130101132504p:plain

Lines:0にしたので以下のようにテキストが消えてしまいました。

f:id:eimei23:20130101132518p:plain

さらにSize Inspectorを見るとWidth Constraintが追加されています。

f:id:eimei23:20130101132530p:plain

これはいけませんね・・・幅が固定になってしまいます。

Labelの幅をドラッグして青い点線のガイドの位置まで広げましょう。

f:id:eimei23:20130101132554p:plain

テキストが表示されるようになり、Size Inspectorを再び確認するとWidth Constraintが削除され、Trailing Space to Superviewが追加されています。

f:id:eimei23:20130101132631p:plain

これでLabelはサイズ自動調整になり、かつ、右端の間隔固定になりました。

次にButtonをFlexible Heightの下に青い点線のガイドにしたがって配置します。

f:id:eimei23:20130101142308p:plain

Flexible Heightとの間と右端にConstraintができるはずです。

f:id:eimei23:20130101132645p:plain

これでFlexible Heightの間隔と右端の間隔が固定されます。Interface Builderが自動で設定したConstraintそのままでよいわけです。

次にButtonのTitleプロパティをLong Textに変更しましょう。

f:id:eimei23:20130101132802p:plain

Buttonの幅に余裕がなくて見栄えが悪くなってしまいましたね。

f:id:eimei23:20130101132809p:plain

さらにButtonにWidth Constraintが追加されてしまいました。幅が固定になってしまうので、これではいけません。

f:id:eimei23:20130101132818p:plain

Buttonを選択してEditorメニューからSize to Fit Contentを選びます。そうするとButtonのサイズが自動調整されます。

f:id:eimei23:20130101132858p:plain

Width Constraintも消えています。

f:id:eimei23:20130101132907p:plain

これでAuto Layoutの設定は完了です。あとはButtonとIBOutletをbindしてButtonを押した時にFlexible Heightのテキストを変更するようになれば良いです。

STAutoLayoutSizeToFitViewController.hにButtonに対応するIBOutletが定義されています。

IBOutlet __weak UIButton *_longTextButton;

STAutoLayoutSizeToFitViewController.mにそのコードがあります。

- (void)buttonDidTap
{
    _flexibleWidthLabel.text = @"Looooooooooooooooong text";
    _flexibleHeightLabel.text = @"Looooooooooooooooooooooooooooooooooooooooooooong text";
}

Subview間の垂直間隔

今回、Flexible Height LabelとButtonの間隔はInterface Builderによって自動で決定されました。これを自分で設定してみましょう。

Buttonを下に移動してFlexible Heightから離してみましょう。

f:id:eimei23:20130101141056p:plain

そうすると青いバーがFlexible Heightの下端へではなく、Superviewの上端へ伸びるようになります。

Constraintを見ると、Top Space to Superviewが追加されています。

f:id:eimei23:20130101141110p:plain

つまりFlexible Heightとの間隔ではなく、Superviewとの間隔が固定されるようになりました。Simulatorで起動しButtonを押す前と押した後は以下のようになります。

f:id:eimei23:20130102091821p:plain

Buttonの位置はFlexible Heightの高さが変わっても下に移動しなくなっています。

これをFlexible Heightとの間隔を固定するようにしてみましょう。

Commandキーを押しながらFlexible HeightとButtonを同時に選択します。

f:id:eimei23:20130101141131p:plain

次に右下のボタンからPin > Vertical Spacingを選択します。

f:id:eimei23:20130101141140p:plain

するとFlexible HeightとButtonの間にConstraintが追加されます。

f:id:eimei23:20130101141150p:plain

必要ないSuperviewとの間隔を固定しているConstraintを選択してDeleteキーを押して削除します。

f:id:eimei23:20130101141156p:plain

削除後

f:id:eimei23:20130101141204p:plain

保存してSimulatorで起動してみましょう。Button押すと以下のようにButtonの位置が下に移動するはずです。

f:id:eimei23:20130102094645p:plain

つまりFlexible Heightとの間隔を固定するようになりました。

このように場合によっては自分でSubviewどうしの間隔を指定する必要があるでしょう。今回は垂直方向の間隔を指定しましたが、水平方向も同じようにできます。その場合はPin > Horizontal Spacingを選択してConstraintを追加します。

以上、今回はサイズ自動調整とSubview間の間隔について説明しました。

次回はSuperview中心へのSubview配置について説明したいと思います。

その4へつづく