1. ホーム
  2. アイオス

[解決済み】Xcode 6でAutoLayout制約を使用してアスペクトフィットの動作をエミュレートする

2022-03-25 19:51:15

質問

AutoLayout を使って、UIImageView のアスペクトフィット コンテンツ モードを彷彿とさせるような方法で、ビューのサイズとレイアウトを変更したいのですが。

Interface Builderのコンテナビューの中にサブビューがあります。このサブビューには固有のアスペクト比があり、これを尊重したいのです。コンテナビューのサイズは、実行時まで不明です。

コンテナビューの縦横比がサブビューより広い場合、サブビューの高さを親ビューの高さと同じにしたい。

コンテナビューの縦横比がサブビューより大きい場合、サブビューの幅を親ビューの幅と同じにしたい。

いずれの場合も、サブビューはコンテナビューの中で水平方向と垂直方向の中央に配置されることを希望します。

Xcode 6またはそれ以前のバージョンで、AutoLayout制約を使用してこれを実現する方法はありますか?理想的にはInterface Builderを使用しますが、そうでない場合は、おそらくプログラムでそのような制約を定義することが可能です。

解決方法は?

スケール・トゥ・フィットではなく、アスペクト・フィットを説明しているのですね。 (この点については質問を編集しました。) サブビューは、縦横比を維持しながら可能な限り大きくなり、その親の内部に完全に収まります。

とにかく、オートレイアウトでできます。 Xcode 5.1では、完全にIBでできます。 それでは、いくつかのビューから始めてみましょう。

ライトグリーンの図は、アスペクト比が4:1である。 深緑のビューのアスペクト比は1:4です。 青いビューが画面の上半分を満たし、ピンクのビューが画面の下半分を満たし、それぞれの緑のビューが縦横比を維持し、コンテナに収まるように、できるだけ拡大されるように制約を設定するつもりです。

まず、青いビューの4辺に制約を作成します。 各辺の最も近い隣人に、距離0になるように固定します。

なお、私は ません。 はまだフレームを更新していません。 制約を設定するときにビューの間に余裕を持たせて、定数を0(または何でも)に手で設定するだけの方が簡単だと思います。

次に、ピンクのビューの左端、下端、右端を、最も近い隣人に固定します。 上辺はすでに青いビューの下辺に拘束されているので、上辺の拘束を設定する必要はありません。

また、ピンクとブルーのビューの間に高さが等しい制約が必要です。 これにより、それぞれが画面の半分を埋めるようになります。

Xcodeに今すぐすべてのフレームを更新するように指示すると、次のようになります。

ということは、これまで設定した制約は正しいということですね。 元に戻して、薄緑色のビューで作業を開始します。

ライトグリーンのビューをアスペクトフィットするには、5つの制約が必要です。

  • ライトグリーンビューの必須・優先アスペクト比制約。この制約は、Xcode 5.1以降でxibまたはstoryboardに作成することができます。
  • ライトグリーンビューの幅が、そのコンテナの幅以下であることを制限する必須優先度の制約です。
  • ライトグリーン・ビューの幅をそのコンテナの幅と同じにする優先度の高い制約。
  • ライトグリーン・ビューの高さがそのコンテナの高さ以下になるように制限する必須優先度の制約。
  • ライトグリーン・ビューの高さがそのコンテナの高さと等しくなるように設定する、優先度の高い制約です。

2つの幅の制約について考えてみましょう。 等しいかそれ以下の制約だけでは、ライトグリーンビューの幅を決定するのに十分ではありません。 曖昧さがあるため、autolayoutはもう1つの(優先度は高いが必須ではない)制約の誤差を最小にする解を選ぼうとします。 誤差を最小にするとは、コンテナの幅にできるだけ近づけながら、必要なless-than-or-equal制約に違反しないようにすることです。

高さ制約も同様です。 そして、アスペクト比の制約も必要であるため、1つの軸に沿ってサブビューのサイズを最大化することしかできません(コンテナがたまたまサブビューと同じアスペクト比である場合を除きます)。

そこで、まずアスペクト比制約を作成します。

そして、コンテナで幅と高さが等しい制約を作ります。

これらの制約を編集して、小なりまたは等しい制約にする必要があります。

次に、コンテナで等しい幅と高さの制約をもう1セット作成する必要があります。

そして、これらの新しい制約を必要な優先度より低くする必要があります。

最後に、サブビューをそのコンテナの中央に配置するようにとのことなので、その制約を設定します。

では、テストとして、ビューコントローラを選択し、Xcodeにすべてのフレームを更新するよう依頼してみます。 これが、私が得たものです。

おっと! サブビューがコンテナを完全に満たすように拡張されています。 これを選択すると、実際にはアスペクト比が維持されていることがわかりますが、アスペクト比を変更するために フィル の代わりに、アスペクト フィット .

問題は、等しくない制約では、どのビューが制約の両端にあるかが重要で、Xcodeは私の期待とは反対の制約を設定したことです。 私は、2つの制約のそれぞれを選択して、その第1項目と第2項目を逆にすることができました。 代わりに、私はサブビューを選択し、制約を大なり小なり変更することにします。

Xcodeはレイアウトを更新します。

次に、下部の深緑色のビューに同じことをすべて行います。 アスペクト比が1:4であることを確認する必要があります(Xcodeは制約を持たなかったので、奇妙な方法でサイズを変更しました)。 手順は同じなので、再度表示することはありません。 これがその結果です。

これで、IBが使用した画面サイズとは異なるiPhone 4Sのシミュレータで実行し、回転のテストができるようになりました。

そして、iPhone 6のシミュレーターでテストすることができます。

最終的な絵コンテをアップロードしたのは このgist をご覧ください。