Unityには、GUIの作成をサポートする通称『uGUI』と呼ばれる機能があります。
ここ最近でずいぶん使いやすくなってきましたが、まだ最初から用意しておいて欲しいUI部品がなかったりします。
あるアプリを開発している時に『ListView』が欲しくなったのですが、uGUIには元から用意されていません。
そこで、AssetStoreを見てみたらいくつか売られていましたが、
頑張ったら作れるんじゃないの?
と調子に乗ってみたところ、なんとかListViewを自作できました。
ここでは、僕なりのListViewの作り方を解説してみます。
ScrollViewを追加する
今回作るListViewですが、基本となるのはScrollViewです。
簡単に言うと、ScrollViewにスクリプトを設定して、ListViewっぽくするだけです。
というわけで、まずは2Dプロジェクトを作成して、[Create - UI - Scroll View] でScrollViewを追加します。

すると、Canvasがない場合は自動的にCanvasが追加され、その下にScrollViewが追加されます。
最初は表示がよくわからないと思うので、まずはCanvasの設定を変更しておきます。
Canvasを選択して、Inspectorの[Render Mode] を[ Screen Space - Camera] に変更し、「Render Camera」を「Main Camera」に設定しておきます。こうしておくと、このCanvasが指定したカメラに対してOverlay表示されるのでみやすくなります。
(実際は、自分の作成するアプリに合わせて変更してください)
こうすると以下のような画面になります。
ちなみにInspectorはこんな感じ。サイズは適当に決めてください。
作成するListViewにもよりますが、今回は縦スクロールのみとするので、「Scrollbar Horizontal」をHierarchyから削除してしまいます。
そして、「Scroll View」を選択して「Scroll Rect (Script)」の「Horizontal」のチェックも外してしまいましょう。
これで、縦スクロールのみのScroll Viewになったので、ListViewの元ができました。
名前も「List View」に変えてしまっておきます。
ListViewnのアイテムを作成
次は、ListViewの1行に表示する項目を集めたアイテムを作成します。
Hierarchy から [Scroll View - Viewport - Content] と開き、Contentの下に空のGameObjectを追加します。
追加した Game Object を選択して、Anchorを変更します。
Pivotを(1, 1)に変更し、Left, Pos Y, Right, Heightをお好みに合わせて設定しておきます。今回は以下のようにしました。
そうしたら、ここで追加したGameObject を ListViewItem 等の名前に変更しておきます。
次に、作成したListViewItemに表示したい項目を入れていきます。今回は、背景色とテキストのみとします。
まずは背景色を追加します。先ほどのListViewItemを選択して、右クリック[UI - Image] で画像を追加して、名前は
Backgroundにしておきましょう。
Backgroundを選択して、InspectorのImageコンポーネントの
Colorを好きな色に設定します。
RectTransformは以下の画像を参考に設定してみてください。Pivotは(1,1)にしておくと良いと思います。
次に、右クリック[UI - Text]でテキストを追加しておきます。Textの設定も以下の画像を参考にしてください。
そうするとこんな感じになります。
ちなみにHierarchyはこんな感じ。
ここまでできたら、ListViewItemをProjectウィンドウにドラッグ&ドロップして、Prefab化しておきます。Prefab化できたら、HierarchyのListItemViewは削除しておきましょう。
これで下準備は完了です。ここからスクリプトを書いていきます。
スクリプトを作成する
ProjectウィンドウでC#スクリプトを作成します。名前は「ListViewController」にしておきましょう。
ファイルを開いたら、まず、「Content」の変数を用意します。そして、あとでListViewに項目を追加していくので、先ほど作成したListViewItemのPrefabも変数にして持っておきましょう。
using UnityEngine;
using System.Collections;
public class ListViewController : MonoBehaviour {
public RectTransform content_;
public GameObject item_prefab_;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
作成したスクリプトを Hierarchy の List View にドラッグ&ドロップして、先ほど作成した変数に Inspector から「_content」にはViewport の 「Content」を、「item_prefab_」には「ListViewItem」をそれぞれセットしておきます。
ListViewの項目を作っていく
ここからListViewに表示する項目を作っていきます。
先ほど作成した、ListViewItemは文字列を表示する箇所があったので、表示する文字列を指定できるようにしましょう。
まずはスクリプトに、表示する文字列を設定する配列を変数として追加します。ここでは「itemList_」としておきましょう。
public class ListViewController : MonoBehaviour {
public RectTransform content_;
public GameObject item_prefab_;
public string[] itemList_;
:
:
そうしたら、今度はUnityのListViewのInspectorビューで「itemList_」に値を設定します。ここではサイズが10、item0〜item9の文字を表示することにしましょう。
ListViewにこれらの項目が設定されたListViewItemを追加していくわけですが、ここで
Vertical Layout Group を使用します。
Vertical Layout Group は、Layout Group の中の1つですが、これは子要素を縦方向に自動的にレイアウトしてくれるコンポーネントです。
このコンポーネントをListViewの Content に設定します。
あとは、作成しておいたListViewItem Prefab をスクリプトからこのContentにスクリプトに追加していくのですが、Contentの高さをListViewItemの高さと追加する数に合わせて調整したいので、Start()のときにListViewItemの高さを取得しておきます。
itemの高さを保持しておく変数を作成し、起動時にStart()で一度ListViewItemのPrefabのインスタンスを作成し、高さを取得しておきます。
ここでは、このItemは使用しないのでDestroyしてしまいます。
private float itemHight_;
// Use this for initialization
void Start () {
GameObject item = GameObject.Instantiate(item_prefab_) as GameObject;
RectTransform rect = item.GetComponent();
itemHight_ = rect.rect.height;
GameObject.Destroy(item);
}
これで、Item1つあたりの高さが取得できたので、実際にListViewの項目を作っていきましょう。やることとしては以下の2つです。
- ListViewItemの個数に合わせてContentの高さを調整する
- Contentの子要素としてListViewItemのインスタンスを設定していく
ListViewの項目を更新する関数を作成します。
private void UpdateListView() {
// item数に合わせてContentの高さを変更する.
int setting_count = itemList_.Length;
float newHeight = setting_count * itemHight_;
content_.sizeDelta = new Vector2(content_.sizeDelta.x, newHeight); // 高さを変更する.
// Contentの子要素にListViewItemを追加していく.
foreach (string itemStr in itemList_) {
GameObject item = GameObject.Instantiate(item_prefab_) as GameObject; // ListViewItem のインスタンス作成.
Text itemText = item.GetComponentInChildren<Text>(); // Textコンポーネントを取得.
itemText.text = itemStr;
RectTransform itemTransform = (RectTransform)item.transform;
itemTransform.SetParent( content_, false ); // 作成したItemをContentの子要素に設定.
}
}
これで、itemList_で指定した文字列がListViewに表示されているはずです。
これでも問題ないのですが、念のためListViewを更新するときに、最初に項目をクリアする処理を入れておきましょう。
private void UpdateListView() {
RemoveAllListViewItem(); // ListViewの項目を一度削除する.
// item数に合わせてContentの高さを変更する.
int setting_count = itemList_.Length;
float newHeight = setting_count * itemHight_;
content_.sizeDelta = new Vector2(content_.sizeDelta.x, newHeight); // 高さを変更する.
:
:
:
}
private void RemoveAllListViewItem() {
foreach (Transform child in content_.transform) {
GameObject.Destroy(child.gameObject);
}
}
これでuGUIでのListViewの作成は完了です!
今回はListViewのアイテムはTextだけにしましたが、Prefab化したListViewItemをカスタマイズすることで、好きな項目を表示することができます。
ぜひお好きなListViewにカスタマイズしてみてください!