[Unity] ContentSizeFitterを使ってコンテンツサイズによって可変なUI要素を作る

## 実行環境
- Unity5.4.0f3

## 事前準備
### 9slice
- コンテンツサイズを拡縮する際にSpriteが9slice対応していないと拡縮時に歪んでしまう
- 9sliceの対応方法についてはいかに記載
  - [[Unity]Imageコンポーネントの基本的な設定 - 9sliceを実装する](http://qiita.com/lycoris102/items/98bc5a5659e4889dd43f#9slice%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B)

## ContentSizeFitter
- https://docs.unity3d.com/ja/current/Manual/script-ContentSizeFitter.html
- ContentSizeFitterコンポーネントがアタッチされている場合、RectTransformのWidth/Heightはレイアウト要素に依存して決定される

### (Horizontal|Vertical)Fit
- 幅/高さをContentSizeFitterによって制御させるかを設定できる
  - 幅はレイアウト要素によって可変でありたいが、高さは固定にしたい等
- 各設定に関しては以下の通り
  - 参考: [Layout Element](https://docs.unity3d.com/ja/current/Manual/script-LayoutElement.html)

|プロパティー||
|---|---|
|Unconstrained|レイアウト要素によって制御させない<br/>RectTransform上で幅/高さを設定可能|
|MinSize|レイアウト要素におけるMin(Width/Height)によって幅/高さが制御される<br/>(MinSizeはそのコンテンツに最低限割り振られる幅/高さ)|
|PrefferedSize|レイアウト要素におけるMin(Width/Height)によって幅/高さが制御される<br/>(PrefferedSizeは利用可能領域が存在する場合にMinSizeより優先して割り振られる幅/高さ)|

## LayoutGroupによってコンテンツサイズを制御する
- Hierarchy上で以下のようなGameObjectの構成を作る

```
// コンポーネントとの違いを明示するためにここではObjectSuffix
- Canvas
  - LayoutGroupObject
     - ItemObject
```

![hierarchy.png](https://qiita-image-store.s3.amazonaws.com/0/102664/98746925-c87e-f18c-1e51-411537233f7b.png)

### LayoutGroupObject
- 以下のコンポーネントをアタッチする
- **Image**
  - SourceImage: 予め9slice対応したSpriteを設定
  - ImageType: Sliced を設定
- **(Vertical|Horizontal|Grid)LayoutGroup**
  - https://docs.unity3d.com/ja/current/Manual/script-VerticalLayoutGroup.html
  - それぞれ(縦|横|格子状)に要素が並ぶリストを作る際に使用する

|プロパティ||
|---|---|
|Padding|リスト内の要素と外枠との余白を設定する|
|Spacing|リスト内の要素同士の間隔を設定する|
|Child Alignment|全ての要素が埋まってない場合に、どこに要素を詰めるか<br/>(どこから要素を開始するかとも言い換えられる)|
|Child Force Expand|利用可能な領域に余りが存在する場合、リスト要素を拡大するか<br/>今回のようなコンテンツのサイズが可変である場合や<br>デザインで要素の大きさが決まっている場合には設定を外す|

- **ContentSizeFitter**
  - (Horizontal|Vertical)Fit: Unconstrained以外の項目を設定することでLayoutGroupのリスト要素の幅/高さおよび個数に応じてサイズが変更されるようになる

![lyoutgroupobject.png](https://qiita-image-store.s3.amazonaws.com/0/102664/2ff0b5c1-1052-8579-344e-fc94aae067f2.png)

### ItemObject
- 以下のコンポーネントをアタッチする
- **LayoutElement**
  - リスト要素におけるRectTransformのWidth/Heightは親のLayoutGroupコンポーネントが制御している
  - リスト要素における幅/高さを設定する場合にはLayoutElementコンポーネントをアタッチする
  - 親のContentSizeFitterに合わせて (Min|Preffered) Size を設定する
- その他のリスト要素に必要なコンポーネント
  - Image ... 等

![image](https://qiita-image-store.s3.amazonaws.com/0/102664/26ddf6eb-b206-3c5f-d72b-8e59657dcfa5.png)

### DEMO
- リスト要素の個数やLayoutElementにおける高さの変動によって親要素もストレッチする

![contentsizefitterlist.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/b5120289-3e12-a414-bd80-bb8ac1069e81.gif)

## TextとLayoutGroupの組み合わせでテキストダイアログを作る
- Hierarchy上で以下のようなGameObjectの構成を作る
  - さっきと殆ど一緒

```
- Canvas
  - LayoutGroupObject
     - TextObject
```

![textlist.png](https://qiita-image-store.s3.amazonaws.com/0/102664/f85387ea-2f7a-00e8-bb00-849f95dcb696.png)

### LayoutGroupObject
- 先ほどと同じコンポーネントをアタッチする
- **Image**
  - 9slice対応を行う
- **(Vertical|Horizontal|Grid)LayoutGroup**
  - テキストと枠が被らないように充分なPaddingを取ることに注意
- **ContentSizeFitter**
  - **Perferred Size**に設定する
  - (MinSizeだと動作しない... 要確認)

### TextObject
- 以下のコンポーネントをアタッチする
- **Text**
  - 文章の開始地点は親要素のLayoutGroupにおけるChild Alignmentで設定する
  - 領域を決める開始地点がそのまま文章の開始地点になるため

### DEMO
- 文章量によって親要素がストレッチする

![contentsizefittertext.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/41c80c18-7e02-4bd8-262a-a11359e37764.gif)

## 参考
- https://docs.unity3d.com/ja/current/Manual/HOWTO-UIFitContentSize.html