Interface Builderでビューを整列、サイズ変更、配布する古いStruts and Springsの方法を理解しています。ただし、Xcode 5で自動レイアウトを使用してビューを均等に分散する方法を理解できないようです。Xcode4を使用してそれを行う方法はありましたが、そのオプションはなくなりました。
7つのボタンが縦に並んでいます。 3.5インチレイアウトでは、見栄えがよくなります。4インチレイアウトで画面をプレビューすると、すべてのボタンがぎっしり詰まっており、最後のボタンの下に大量のスペースがあります。
私はそれらを同じ高さに保ちたいが、それらが画面全体に広がることができるようにそれらの間のスペースが曲がることができるようにしたい。
ボタンの高さを調整してスペースを埋めることができましたが、それは望ましい動作ではありません。 Auto Layoutを使用して古いSpringsの動作を置き換える方法を学びたいのですが、Interface Builderでそれを行う方法が見つからないようです。
上ボタンは、下ボタンと下エッジも同様に、上エッジからの固定スペースでも、上エッジからの比例スペースでも構いません。それらは私にとってそれほど重要ではありません、私はどちらでも良いです。
しかし、ビュー内の各アイテム間に余分なスペースを均等に分散する方法を実際に把握する必要があります。
[〜#〜] edit [〜#〜]iOS 9では、UIStackViewが配布を自動的に実行するため、この手法は不要になることに注意してください。 別の答え を追加して、その仕組みを説明します。
Interface Builderのみでこれを行う最も簡単な方法は(コードで制約を構築するのではなく)、「スペーサー」ビューを使用することです。
上下のボタンを絶対に配置します。
すべてのボタンの間にスペーサービューを配置します。制約を使用して、水平方向に配置し(水平方向に中央に配置するのが最も簡単です)、幅を設定します。
定数を0にして、各ボタンとその上下のスペーサービューの間に制約を設定します。
すべてのスペーサービューを選択し、それらの高さを等しく設定します。
最初のスクリーンショットは、これをIBで設定することを示しています。
制約を設計している間、どのように見えるかを見てほしいので、「見当違いのビュー」については意図的に修正していません。 4インチ画面と3.5インチ画面の両方での結果は次のとおりです。
このテクニックがどのように機能するかを示すために、スペーサービューを黒のままにしましたが、もちろん実際には、それらを透明にして非表示にします!そのため、ユーザーにはボタンが表示され、画面のどちらの高さに均等に配置されます。
この手法を使用する理由は、平等の概念が求めている値の分布を実行しますが、制約はビューのアスペクト間でのみ平等を適用できるためです。したがって、他の物と同等にすることができるようにするために、追加のビュー(スペーサービュー)が必要です(ここでは、スペーサービューの高さ)。
明らかに、より柔軟なアプローチは、コードで制約を割り当てることです。これは気が遠くなるかもしれませんが、 この種のこと のような、あなたを助けるサードパーティのコードがたくさんあります。
たとえば、高さが4つのボタンの最大垂直分布を指示する境界として機能する(おそらく不可視の)スーパービューがある場合、constant
の0
を使用して、トップをそのスーパービューの垂直中央に固定できます。しかし、0.000001
、0.666667
、1.33333
、2.0
のmultiplier
(4つのボタンがある場合);画面の高さなどに応じてスーパービューのサイズが変更されても、ボタンは垂直に配置されたままになります。 [Xcode 5.1では、Interface Builderで設定できますが、Xcodeの以前のバージョンでは設定できません。]
IOS 9/Xcode 7では、この問題はIBで簡単に解決されます。ボタン(または垂直に配置するもの)を選択し、[エディター]> [埋め込み]> [スタックビュー]を選択します。次に、単にスタックビューを構成します。
スタックビュー自体の位置とサイズを決める制約を提供します。たとえば、スタックビューの4つのエッジをスーパービューの4つのエッジに固定します。
スタックビューの属性を設定します。この場合、垂直軸、塗りつぶしの配置、等間隔の分布が必要です。
それで全部です!ただし、コードで同じことを手動で行うことはまだ可能であるため、これがどのように機能するのか興味があります。スタックビューは、スペーサーviewsを挿入するのではなく、スペーサーguidesを挿入することによって配信を実行します。ガイド(UILayoutGuide)は、レイアウトの制約のためにビューのように動作する軽量のオブジェクトですが、ビューではないため、非表示にする必要がなく、ビューのオーバーヘッドを一切持ちません。
説明のために、スタックビューの動作をコードで説明します。垂直に分散する4つのビューがあるとします。分布以外のすべてに制約を割り当てます。
それらはすべて絶対的な高さの制約があります
左がスーパービューの左に固定され、右がスーパービューの右に固定されています
トップビューの上部はスーパービューの上部に固定され、ボトムビューの下部はスーパービューの下部に固定されます
ここで、4つのビューへの参照がviews
、配列としてあると仮定します。次に:
let guides = [UILayoutGuide(), UILayoutGuide(), UILayoutGuide()]
for guide in guides {
self.view.addLayoutGuide(guide)
}
NSLayoutConstraint.activateConstraints([
// guide heights are equal
guides[1].heightAnchor.constraintEqualToAnchor(guides[0].heightAnchor),
guides[2].heightAnchor.constraintEqualToAnchor(guides[0].heightAnchor),
// guide widths are arbitrary, let's say 10
guides[0].widthAnchor.constraintEqualToConstant(10),
guides[1].widthAnchor.constraintEqualToConstant(10),
guides[2].widthAnchor.constraintEqualToConstant(10),
// guide left is arbitrary, let's say superview margin
guides[0].leftAnchor.constraintEqualToAnchor(self.view.leftAnchor),
guides[1].leftAnchor.constraintEqualToAnchor(self.view.leftAnchor),
guides[2].leftAnchor.constraintEqualToAnchor(self.view.leftAnchor),
// bottom of each view is top of following guide
views[0].bottomAnchor.constraintEqualToAnchor(guides[0].topAnchor),
views[1].bottomAnchor.constraintEqualToAnchor(guides[1].topAnchor),
views[2].bottomAnchor.constraintEqualToAnchor(guides[2].topAnchor),
// top of each view is bottom of preceding guide
views[1].topAnchor.constraintEqualToAnchor(guides[0].bottomAnchor),
views[2].topAnchor.constraintEqualToAnchor(guides[1].bottomAnchor),
views[3].topAnchor.constraintEqualToAnchor(guides[2].bottomAnchor)
])
(明らかに、ループを使用してコードをより短く、短くすることもできますが、パターンとテクニックを確認できるように、明確にするために意図的にループを展開しました。)