Unityな日々(Unity Geek)

Unityで可視化アプリを開発するための試行錯誤の覚書

iOS用のレスポンシブなUIをつくる

iOSデバイスにはさまざまな解像度、アスペクト比があり、それぞれに適切なUIとなるような工夫がいる。

参考: unitygeek.hatenablog.com

実現したいUI:トリミングとストレッチ

たとえば、次のようなUIデザインを実現したいとする。

  1. 背景の画像は画面の縦サイズにあわせ、横方向はトリミングされる。
  2. ボタンを3つ配置したメニューバーは、画面の横いっぱいに表示し、バー内にボタンを3等分して配置する。
  3. テキストボックスは、横幅一定、高さはテキスト量によって変える。

具体的な完成イメージは次のようなものだ。2つの画面の解像度・アスペクト比はそれぞれ、iPhone5s, iPad Retinaを想定している。 背景の人物の写真は、iPhoneでは左右がトリミングされている。ボトムの黒色のメニューバーは、iPhone, iPadそれぞれに横方向いっぱいに表示され、ボタンは3等分されて配置されている。

f:id:yasuda0404:20150723184213p:plainiPadでの画面イメージ

f:id:yasuda0404:20150723184226p:plainiPhoneでの画面イメージ

実装方法

左右トリミング
  1. まず、カメラ画面全体にひろがるCanvasを作る。 このためには、
  2. CanvasのプロパティRender Modeを'Scressn Space - Overlay'にする。
  3. Canvas ScalerのReference Resolutionを想定するデバイスの画面サイズの最大値にする。 (iOSについては、現状最大のスクリーンサイズはiPad Retinaの1536x2048ピクセルなので、この値を採用。)

参考:iOS - iPhone/iPad解像度(画面サイズ)早見表 - Qiita

  • Canvas ScalerのScreen Match Modeを'Match Width or Height'にし、Height側の端(=1)にする。 (こおオプションは、画面の幅にあわせるか(Width)、高さにあわせるか(Height)を指定するもの。ちなみに、'Expand'とすると画面は画像いっぱいに表示され画像の一部ははみ出し、'Shrink'にすると画像すべてを画面におさめ隙間ができる。)

  • Canvasの下に表示したい画像のUIオブジェクトを作成(ImageまたはRawImage)。このオブジェクトのWidth/Heightを親CanvasのReference Width/Heightにあわせる。

f:id:yasuda0404:20150723185708p:plain

以上で画像は高さ方向にいっぱいに表示され、左右はトリミングされる。

ストレッチ&均等配置するメニューバー

いくつか方法あるが、自動レイアウトのコンポーネントを使う方法が一番簡単。

まず、親UIオブジェクト('ButtonBar')を作り、ストレッチ&均等配置したいオブジェクト('Button')を'ButtonBar'の子にする。画面上のボタンの並び順は、シーンビューでのボタンの並び順と同じになるので、並べたい順番に入れ替える。

'ButtonBar'のRectTransformは、横方向をいっぱいまでストレッチ、縦方向を高さ指定(Height)の設定にする。子オブジェクトであるボタンはこの範囲で均等配置されることになる。PosYはバーのY方向位置が望ましくなるように決める。

f:id:yasuda0404:20150723190605p:plain

'ButtonBar'に、Layout-HorizontalLayoutGroupコンポーネントを付与する。'Child Force Expand'のWidth, Height両方にチェックを入れると、子要素が親要素の大きさいっぱいに広がる。具体例でいうと、子要素がText要素の場合、Widthが親要素と同じになり、子要素自身にWidthを指定できなくなる。

f:id:yasuda0404:20150723185857p:plain

f:id:yasuda0404:20150723185916p:plain

子要素にWidthを指定したい場合は、'Child Force Expand'のWidthのチェックをはずす。これで子要素にLayoutElementを付与できるようになり、PreferredWidthを任意に指定できる。

各Buttonコンポーネントの最小値(Min Width/Height)・推奨値(Preferred Width/Height)・相対的な比率(Flexible Width/Height)は、各ButtonのLayout Propertiesで確認できる。

f:id:yasuda0404:20150727143937p:plain

これらの値を変更したい場合は、Layout-Layout Elementコンポーネントを付加する。たとえば、3つのボタンのサイズ比率を2:1:1にしたい場合は、最初のボタンのFlexibleWidthを2にし、残りの同パラメータを1にすればよい。Layout Propertiesの該当する値が自動的に変わる。

f:id:yasuda0404:20150727144131p:plain

高さ方向可変のテキストボックス

シーンビュー上のText要素に、Layout-Constant Size Fitterコンポーネントを付加する。Vertical Fitを'Preferred Size'に設定。Text要素のPreferred SizeはText量によって変わるため、これに高さ方向をあわせるという考え方。(Preferred HeightとはWidthを固定した場合の高さ。逆にPreferred Widthとはテキストを1行にした時の幅。…ということらしい)

f:id:yasuda0404:20150727144833p:plain

また、ヘッダーのように高さ方向一定の要素は、Layout Element要素を付加し、Preferred Heightに固定値を与える。

f:id:yasuda0404:20150727161317p:plain

f:id:yasuda0404:20150727145012p:plain

上の操作でText要素自体の高さ可変になるが、Text要素やヘッダー要素の親要素であるパネルサイズもあわせて変えたい。このためには親要素に、Layout-Constant Size FitterとLayout−Vertical Layout Groupの2つのコンポーネントを付加する。 Paddingを調整することで、余白を持たせることができる。

f:id:yasuda0404:20150727161638p:plain

完成

シーンビューは次のようになる。
白枠がカメラ描画範囲。背景画像は高さ方向が描画範囲いっぱいになり、アスペクト比が保たれる。
メニューバーは、描画範囲いっぱいに広がり、3つのボタンが均等に配置されている。

f:id:yasuda0404:20150723191050p:plain

Editor上ではカメラの描画範囲が横長のため、カメラの背景(Skybox)が見えてしまっているが、iPhoneiPadのPortraitで見ると、冒頭の目標画面イメージのとおりになっている。