AutoLayout を使用して、UIImageView のアスペクト フィット コンテンツ モードを彷彿とさせる方法でビューのサイズとレイアウトを設定したいと考えています。
Interface Builder のコンテナ ビュー内にサブビューがあります。サブビューには、尊重したい固有のアスペクト比があります。コンテナ ビューのサイズは、実行時まで不明です。
コンテナ ビューのアスペクト比がサブビューよりも広い場合は、サブビューの高さを親ビューの高さと同じにします。
コンテナ ビューのアスペクト比がサブビューよりも高い場合は、サブビューの幅を親ビューの幅と同じにします。
どちらの場合でも、サブビューをコンテナ ビュー内で水平方向と垂直方向に中央に配置する必要があります。
Xcode 6 または以前のバージョンで AutoLayout 制約を使用してこれを実現する方法はありますか? 理想的には Interface Builder を使用しますが、そうでない場合は、プログラムでそのような制約を定義することも可能かもしれません。
ベストアンサー1
あなたが説明しているのは、スケール トゥ フィットではなく、アスペクト フィットです。(この点に関して質問を編集しました。) サブビューは、アスペクト比を維持し、親内に完全に収まるように、可能な限り大きくなります。
とにかく、自動レイアウトでこれを行うことができます。Xcode 5.1 以降では、これをすべて IB で行うことができます。いくつかのビューから始めましょう。
ライト グリーンのビューのアスペクト比は 4:1 です。ダーク グリーンのビューのアスペクト比は 1:4 です。ブルーのビューが画面の上半分を占め、ピンク色のビューが画面の下半分を占め、各グリーンのビューがアスペクト比を維持しながらコンテナーに収まるように、制約を設定します。
まず、青いビューの 4 つの辺すべてに制約を作成します。各辺で最も近い隣の辺にピン留めし、距離を 0 にします。マージンをオフにします。
フレームはまだ更新していないことに注意してください。制約を設定するときにビュー間にスペースを残し、手動で定数を 0 (または任意の値) に設定する方が簡単だと思います。
次に、ピンクのビューの左、下、右の端を最も近い隣の端に固定します。上端はすでに青いビューの下端に制約されているため、上端の制約を設定する必要はありません。
また、ピンクと青のビューの高さを等しくする制約も必要です。これにより、それぞれのビューが画面の半分を占めるようになります。
ここで Xcode にすべてのフレームを更新するように指示すると、次のようになります。
これまで設定した制約は正しいので、それを元に戻して、薄緑色のビューで作業を開始します。
ライトグリーンのビューをアスペクト フィッティングするには、次の 5 つの制約が必要です。
- ライトグリーンのビューで必要な優先度のアスペクト比制約。この制約は、Xcode 5.1 以降を使用して xib またはストーリーボードで作成できます。
- ライトグリーンのビューの幅をコンテナーの幅以下に制限する必須の優先度制約。
- ライトグリーンのビューの幅をコンテナーの幅と同じに設定する優先度の高い制約。
- ライトグリーンのビューの高さをコンテナーの高さ以下に制限する必須の優先度制約。
- ライトグリーンのビューの高さをそのコンテナーの高さと同じに設定する優先度の高い制約。
2 つの幅の制約について考えてみましょう。「以下」の制約だけでは、ライト グリーンのビューの幅を決定するのに十分ではありません。この制約に適合する幅は多数あります。あいまいさがあるため、自動レイアウトでは、もう一方の制約 (優先度は高いが必須ではない) のエラーを最小限に抑えるソリューションを選択しようとします。エラーを最小限に抑えるということは、必要な「以下」の制約に違反せずに、幅をコンテナーの幅にできるだけ近づけることを意味します。
高さの制約でも同じことが起こります。また、アスペクト比の制約も必要なので、サブビューのサイズを最大化できるのは 1 つの軸に沿ってのみです (コンテナーのアスペクト比がサブビューと同じでない限り)。
まず、アスペクト比の制約を作成します。
次に、コンテナに等しい幅と高さの制約を作成します。
これらの制約を「以下」の制約に編集する必要があります。
次に、コンテナーに等しい幅と高さの制約の別のセットを作成する必要があります。
そして、これらの新しい制約を必要な優先度よりも低くする必要があります。
最後に、サブビューをコンテナーの中央に配置するように要求されたので、その制約を設定します。
ここで、テストとして、ビュー コントローラーを選択し、Xcode にすべてのフレームを更新するように指示します。結果は次のようになります。
おっと!サブビューが拡大してコンテナを完全に埋め尽くしました。これを選択すると、実際にはアスペクト比が維持されていることがわかりますが、アスペクトフィットではなくアスペクトフィルが実行されています。
問題は、より小さいか等しい制約では、どのビューが制約の両端にあるかが重要であり、Xcode が私の期待とは逆の制約を設定していることです。2 つの制約をそれぞれ選択して、最初の項目と 2 番目の項目を逆にすることもできます。代わりに、サブビューを選択して、制約をより大きいか等しいに変更します。
Xcode はレイアウトを更新します:
次に、下部のダーク グリーンのビューに対して同じ操作をすべて実行します。アスペクト比が 1:4 であることを確認する必要があります (制約がないため、Xcode は奇妙な方法でサイズを変更します)。手順は同じなので、再度表示しません。結果は次のとおりです。
これで、IB が使用したのとは異なる画面サイズを持つ iPhone 4S シミュレーターで実行し、回転をテストできるようになりました。
iPhone 6 シミュレーターでテストできます:
最終ストーリーボードをアップロードしましたこの要点あなたの便宜のため。