【Swift】Pin制約の使い方。部品と部品の最短距離の制約を追加する。(Swift 2.1、XCode 7.2)
Pin制約とは
前回の記事で複数部品を選択したAuto Layout(以下、オートレイアウト)について説明した。⇒「記事」
前回は「部品の左端から他の部品の左端まで」、「部品の右端から他の部品の右端まで」など、同じ端同士の距離の制約について説明した。
今回は「部品の左端から他の部品の右端まで」、「部品の左端から画面の右端まで」など、逆の端同士、いわゆる部品間の最短距離の制約について説明する。これをPin制約という。
検証するために、いつも通りデバイス画面にラベルを追加する。
今回は部品間の距離が把握しやすいようにラベルの外見を変更しておこう。ラベルをクリックしたあとにアトリビュートインスペクタボタン(下図黄緑枠)を押す。すると設定画面が表示されるので、Colorを白色、Backgroundを青色、Fontサイズを30に変更した。
配置したラベルを常に左上隅から近いところに表示したい場合について考える。
例えば、下図のように、部品をクリックしたあとに赤枠のalignボタンから「Horizontally in Container -58」、「Vertically in Container -229」の制約を追加した場合、縦画面で表示した場合は画面左上に表示されるが、端末を倒して横画面にした場合はどうなるか。
以下の動画のように、横画面にした段階でラベルはいなくなる。
なぜなら、追加した制約は画面の中心からの距離を指定するものなので、横画面の中心から同じ距離の場所が画面外になってしまうためである。
画面端と部品の距離の制約を追加する
「iPadでもiPhoneでも、縦画面でも横画面でも、画面端の近くに部品を表示したい。」そんなときにPin制約を使う。
ラベルをクリックしたあとに下図青枠のPinボタンを押す。吹き出しの設定画面で、赤枠内の2つのマークをクリックして「Add 2 Constraints」ボタンを押す。これで「画面左端からラベル左端までの距離」と「画面上端からのラベル上端までの距離」が制約として追加される。
上図黄緑枠の「Constrain to margins」は、画面左右端の余白部分を考慮するかどうかの設定である。これにチェックを入れると画面左右に20pxの余白が入る。
今回の例では「Constrain to margins」にチェックを入れたので、画面左端の余白20pxのあとに22pxの距離をとることになり、実際は42ピクセルの距離になるということだ。
以下は制約を追加したあとのプレイ動画。縦画面でも横画面でもラベルは常に画面左上に表示されるようになった。
ちなみに、あとから余白の考慮が不要になった場合は、制約を選択したあとにアトリビュートインスペクタボタン(黄緑枠)を押して、Second Itemの中の「Relative to margin」のチェックを外すと余白を考慮しない設定に変更される。
上からの距離と下からの距離の制約を追加した場合
「画面上端から部品までの距離」と「画面左端から部品までの距離」は問題なく追加できた。要するに、L字方向の距離の制約は問題なく追加できる。
では、「画面上端から部品までの距離」と「画面下端から部品までの距離」などの部品を挟むような制約を追加した場合はどうなるか。試してみよう。
下図のようにラベルを追加したあと青枠のPinボタンを押して設定画面を開く。黄緑枠の2つのボタンをクリックしたあとに「Add 2 Constraints」ボタンを押して制約を追加する。水平方向の位置の制約はいつもの手順で「Horizontally in Container 0」を追加する。
端末を倒して横画面にしてみよう。以下は実際のプレイ動画。ラベルが画面上から消えた。
端末を倒したときに以下のメッセージが出力された。
1 2 3 4 5 |
2016-03-26 23:04:42.653 TestProject4[2605:239901] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. |
横画面にすると下図のように部品の位置が定まらなくなるため発生したエラーである。
左からの距離と右からの距離の制約を追加した場合
では、今度は「画面左端から部品までの距離」と「画面右端から部品までの距離」を追加した場合はどうなるか試してみよう。
先ほどと同じようにラベルを追加したあと青枠のPinボタンを押して設定画面を開く。黄緑枠の2つのボタンをクリックしたあとに「Add 2 Constraints」ボタンを押して制約を追加する。垂直方向の位置の制約はいつもの手順で「Vertically in Container 0」を追加する。
端末を倒して横画面にしてみよう。以下は実際のプレイ動画。エラーは発生せずにラベルが横に引き延ばされた。
横画面にすると画面端から部品端までの距離が下図のようになる。ラベルのサイズの制約は追加してないので、制約に合うようにラベルが引き延ばされたということだ。これは入力ボックスなど、画面のサイズに合わせてサイズを伸縮させたいときに使えそうだ。
つまり、上下、左右などの一直線のPin制約を追加するときは、画面サイズが変わったときに上図で書いた矢印イメージの終端が交わらないように設計する必要があるということである。
部品と部品の距離の制約を追加する
Pin制約は画面端からの距離だけではなく、部品と部品の間の距離も設定できる。
例えば、下図のようにもう一つのラベルをデバイス画面に追加したあと、Pin設定画面から下図赤枠をクリックする。すると距離を設定できる部品の一覧が表示されるので、「ラベル1」にチェックが入っていることを確認する。
マークをクリック、「Add 1 Constraints」ボタンで制約を追加すると、
ラベル2の垂直方向の制約に、ラベル2の上端からラベル1の下端までの距離が追加される。
部品間のPin制約を追加したいときに、対象の部品が追加したい方向に無いときは追加できないので注意すること。
例えば、下図のようにラベル2を追加したが、ラベル2の真っ直ぐ上にはラベル1が存在しない。そのため、pin設定画面から下図赤枠をクリックしても、距離を設定できる部品の一覧にラベル1は現れない。
次回はPin制約の続きで、部品のサイズに関する制約について説明する。