前回のつづき

今回はViewを横並びに配置する方法について。横画面になったときや、テキストの内容が変わった時に、適切な幅に変わるようにします。

サンプルコード: https://github.com/stack3/iOSAutoLayoutSamples

サンプルコードを起動し、Resize Horizontalを選択すると、以下の画面が表示されます。

01

横画面にするとTextFieldの横幅がリサイズされます。

02

Long Text Buttonを押すと、Search Button、Nameのテキストが変わり、幅が伸びます。それにあわせてTextFieldの幅が狭くなります。

03

自分でConstraintを設定する

STResizeHorizontalViewController.xibを開いてください。

Viewに配置されたSubviewを選択すると、Constraintが確認できます。(Ctrlキーを押しながら選択すると複数選択できます)

01

これを一旦すべて削除しましょう。

Resolve Auto Layout Issuesボタンを押して、Clear All Constraints in Viewを選択します。

05

 

すべてのConstraintが削除されました。

02

 

起動してみるとNavigationBarの下に隠れてしまいます。

03

横画面にしてもTextFieldの幅が調整されません。

04

 

Long Text Buttonを押した時も、Labelの幅が調整されません。

05

 

Constraintを追加していきましょう。

まず上のTextFieldを選択。

06

 

Pinボタンを押して、以下のようにConstraintを選択してAdd 4 Constraintsボタンを押します。

10a

 

Constraintが追加されました。ただ隣接するもの含めてConstraintが不足しているのでオレンジ色になっています。

08

 

Search Buttonを選択します。

09

 

以下のようにConstraintを選択して、Add 3 Constraintsボタンを押します。

13

 

左側へはConstraintを追加しないことに注意です。先ほどTextFieldから右側へConstraintを追加したからです。

もし追加してしまうと、以下のように重複して余分なConstraintができてしまいます。間違って追加したら消しておきましょう。

14

 

これでTextFieldとSearch ButtonのConstraintが設定できました。

10

まだ下のViewとのConstraintがオレンジ色になっています。これも下のViewのConstraintを設定すれば解決されます。

Name Labelを選択し、以下のようにConstraintを選択し、Add 3 Constraintsを押します。

11

 

以下のようにConstraintが設定されました。

12

 

Name Labelの隣のTextFieldを選択し、以下のようにConstraintを選択肢、Add 2 Constraintsを押します。

19

 

以下のようにConstraintが追加されます。

13

 

Long Text Buttonの上のTextFieldへ向かってConstraintがオレンジ色になっているのは、水平方向のConstraintが不足しているからです。

Long Text Buttonを選択して、Pinボタンを押し、右側のConstraintを選択し、Add 1 Constraintを押します。

22

 

Constraintが追加され、オレンジ色だったものも青色に変わりました。

15

 

アプリを起動して確認してみると、うまく動作するはずです。

01

02

Content Hugging Priority

うまく動作していますが、1点説明が漏れています。それはContent Hugging Priorityというものです。

TextFieldを選択します。

16

 

Size Inspectorを開くとContent Hugging Priorityという項目があるはずです。

26

Horizontalの方が249になっていますが、デフォルトは250です。サンプルコードを作った際に、私が調整して249にしました。

Constraintを自分で設定する前に、一度、Clear All Constraints in Viewで、すべてのConstraintを削除しました。しかし、Content Hugging Priorityは、リセットされずに残ってしまったようです。

これを250に戻してみましょう。

27

 

Constraintがオレンジ色になってしまいました。

17

 

この状態でアプリを起動してみましょう。そして横画面にしてください。

29

 

レイアウトが意図したものと異なりますね。iOS 7からボタンがテキストだけになってしまったのでわかりづらいですが、これはTextFieldではなくSearch Buttonの幅が広くなってしまっています。背景色を変えると確認しやすいです。

30

 

なぜこうなってしまうのでしょうか。

TextFieldとSearch Buttonの水平方向のConstraintは以下のようになっています。

18

左から順に、

  • TextFieldとSuperviewの左端の間隔固定
  • TextFieldとSearchButtonの間隔固定
  • SearchButtonとSuperviewの右端の間隔固定

になっています。

このConstraintを守るためには、横画面にした時、TextField、Search Buttonどちらかの幅を広げる必要があります。そのためにはその情報が必要になります。それがContent Hugging Priorityです。

TextFieldのContent Hugging Priorityを再び249にすると、Constraintが青色になります。この状態で起動すると、きちんと動作するはずです。もしくはTextFieldのContent Hugging Priorityは250、Search Buttonの方を251にしても、うまく動作します。このように水平方向、もしくは垂直方向にViewを並べた時は、Content Hugging Priorityの調整が必要なことがあります。

Search Buttonの幅を固定にする

TextFieldとSearch Buttonの並びをContent Hugging Priorityの設定をせずに、うまくやる方法があります。それはSearch Buttonの幅を指定することです。

TextFieldとSearch ButtonのContent Hugging Priorityを両方250にして、Search Buttonを選択します。

19

 

Pinボタンを押して、Widthにチェックを入れて、Add 1 Constraintを押します。

33.png 2013-10-12 16-17-54

 

Search Buttonの幅を示すConstraintが追加されました。

20

 

同時に先ほどまでオレンジ色だったConstraintが青色になっています。

21

Search Barの幅が固定なら、TextFieldの方を伸ばせば良いとAuto Layoutが判断できるようになったからです。

 

アプリを起動して横画面にすると、実際にうまく行っているのを確認できるはずです。

02

 

ただ、幅を固定する方法には問題があることに注意です。Long Text Buttonを押してみましょう。

36

このようにボタンのタイトルが省略されてしまいます。

今回のサンプルのような形でボタンのタイトルが変わることはあまりないかもしれません。ただ、言語の国際化対応でボタンのタイトルが変わることはあります。それによって自動的に適切なボタン幅となるようにするには、WidthのConstraintを使わず、Content Hugging Priorityを使うべきでしょう。

※ Auto LayoutではWidth、HeightのConstraintが指定されていないViewは、状況に応じて幅や高さが可変する状態にあることに注意してください。

その6へつづく