1.下载插件Tree View导入到工程中。下载地址:https://assetstore.unity.com/packages/tools/gui/tree-view-65364。
2.新建场景,新建Canvas,将Assets\Battlehub\UIControls\Prefabs\TreeView.prefab拖入Canvas下。
3.点击【GameObject】【Create Empty】,创建一个空实体,命名为LoadTreeviewData。
4.创建LoadTreeviewData.cs脚本,打开编辑,将TreeViewDemo中的代码(类名除外)复制到脚本中(全部代码见后文)。
5.自定义数据给大家MyCustomData。
6.在LoadTreeviewData的Start()函数中添加Treeview数据,改写数据绑定ItemDataBinding和节点展开函数ItemExpanding。
7.将TreeView拖入变量框,运行即可。
using Battlehub.UIControls;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class MyTreeview : MonoBehaviour {
public TreeView TreeView;
public static bool IsPrefab(Transform This)
{
if (Application.isEditor && !Application.isPlaying)
{
throw new InvalidOperationException("Does not work in edit mode");
}
return This.gameObject.scene.buildIndex < 0;
}
private void Start()
{
if (!TreeView)
{
Debug.LogError("Set TreeView field");
return;
}
List<MyCustomData> dataItems = new List<MyCustomData>();
dataItems.Add(new MyCustomData("宝成线", NodeType.RailwayLine));
MyCustomData data = new MyCustomData("成昆线", NodeType.RailwayLine);
data.childs.Add(new MyCustomData("成都段", NodeType.RailwaySection));
data.childs.Add(new MyCustomData("云南段", NodeType.RailwaySection));
dataItems.Add(data);
dataItems.Add(new MyCustomData("京广线", NodeType.RailwayLine));
//subscribe to events
TreeView.ItemDataBinding += OnItemDataBinding;
TreeView.SelectionChanged += OnSelectionChanged;
TreeView.ItemsRemoved += OnItemsRemoved;
TreeView.ItemExpanding += OnItemExpanding;
TreeView.ItemBeginDrag += OnItemBeginDrag;
TreeView.ItemDrop += OnItemDrop;
TreeView.ItemBeginDrop += OnItemBeginDrop;
TreeView.ItemEndDrag += OnItemEndDrag;
//Bind data items
TreeView.Items = dataItems;
}
private void OnItemBeginDrop(object sender, ItemDropCancelArgs e)
{
//object dropTarget = e.DropTarget;
//if(e.Action == ItemDropAction.SetNextSibling || e.Action == ItemDropAction.SetPrevSibling)
//{
// e.Cancel = true;
//}
}
private void OnDestroy()
{
if (!TreeView)
{
return;
}
//unsubscribe
TreeView.ItemDataBinding -= OnItemDataBinding;
TreeView.SelectionChanged -= OnSelectionChanged;
TreeView.ItemsRemoved -= OnItemsRemoved;
TreeView.ItemExpanding -= OnItemExpanding;
TreeView.ItemBeginDrag -= OnItemBeginDrag;
TreeView.ItemBeginDrop -= OnItemBeginDrop;
TreeView.ItemDrop -= OnItemDrop;
TreeView.ItemEndDrag -= OnItemEndDrag;
}
private void OnItemExpanding(object sender, ItemExpandingArgs e)
{
MyCustomData dataItem = (MyCustomData)e.Item;
if (dataItem.childs.Count > 0)
{
//Populate children collection
e.Children = dataItem.childs;
}
}
private void OnSelectionChanged(object sender, SelectionChangedArgs e)
{
#if UNITY_EDITOR
//Do something on selection changed (just syncronized with editor's hierarchy for demo purposes)
UnityEditor.Selection.objects = e.NewItems.OfType<GameObject>().ToArray();
#endif
}
private void OnItemsRemoved(object sender, ItemsRemovedArgs e)
{
//Destroy removed dataitems
for (int i = 0; i < e.Items.Length; ++i)
{
GameObject go = (GameObject)e.Items[i];
if (go != null)
{
Destroy(go);
}
}
}
/// <summary>
/// This method called for each data item during databinding operation
/// You have to bind data item properties to ui elements in order to display them.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnItemDataBinding(object sender, TreeViewItemDataBindingArgs e)
{
MyCustomData dataItem = e.Item as MyCustomData;
if (dataItem != null)
{
//We display dataItem.name using UI.Text
Text text = e.ItemPresenter.GetComponentInChildren<Text>(true);
text.text = dataItem.name;
//Load icon from resources
Image icon = e.ItemPresenter.GetComponentsInChildren<Image>()[4];
icon.sprite = Resources.Load<Sprite>("cube");
//And specify whether data item has children (to display expander arrow if needed)
if (dataItem.name != "TreeView")
{
e.HasChildren = dataItem.childs.Count > 0;
}
}
}
private void OnItemBeginDrag(object sender, ItemArgs e)
{
//Could be used to change cursor
}
private void OnItemDrop(object sender, ItemDropArgs e)
{
if (e.DropTarget == null)
{
return;
}
Transform dropT = ((GameObject)e.DropTarget).transform;
//Set drag items as children of drop target
if (e.Action == ItemDropAction.SetLastChild)
{
for (int i = 0; i < e.DragItems.Length; ++i)
{
Transform dragT = ((GameObject)e.DragItems[i]).transform;
dragT.SetParent(dropT, true);
dragT.SetAsLastSibling();
}
}
//Put drag items next to drop target
else if (e.Action == ItemDropAction.SetNextSibling)
{
for (int i = e.DragItems.Length - 1; i >= 0; --i)
{
Transform dragT = ((GameObject)e.DragItems[i]).transform;
int dropTIndex = dropT.GetSiblingIndex();
if (dragT.parent != dropT.parent)
{
dragT.SetParent(dropT.parent, true);
dragT.SetSiblingIndex(dropTIndex + 1);
}
else
{
int dragTIndex = dragT.GetSiblingIndex();
if (dropTIndex < dragTIndex)
{
dragT.SetSiblingIndex(dropTIndex + 1);
}
else
{
dragT.SetSiblingIndex(dropTIndex);
}
}
}
}
//Put drag items before drop target
else if (e.Action == ItemDropAction.SetPrevSibling)
{
for (int i = 0; i < e.DragItems.Length; ++i)
{
Transform dragT = ((GameObject)e.DragItems[i]).transform;
if (dragT.parent != dropT.parent)
{
dragT.SetParent(dropT.parent, true);
}
int dropTIndex = dropT.GetSiblingIndex();
int dragTIndex = dragT.GetSiblingIndex();
if (dropTIndex > dragTIndex)
{
dragT.SetSiblingIndex(dropTIndex - 1);
}
else
{
dragT.SetSiblingIndex(dropTIndex);
}
}
}
}
private void OnItemEndDrag(object sender, ItemArgs e)
{
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.J))
{
TreeView.SelectedItems = TreeView.Items.OfType<object>().Take(5).ToArray();
}
else if (Input.GetKeyDown(KeyCode.K))
{
TreeView.SelectedItem = null;
}
}
}
enum NodeType { RailwayLine = 0, RailwaySection = 1, RailwaySegment = 2, RailwayStation = 3 }
class MyCustomData
{
public List<MyCustomData> childs;
public NodeType nodeType;
public string name;
public object tag;
public MyCustomData(string na, NodeType nt)
{
childs = new List<MyCustomData>();
name = na;
nodeType = nt;
}
}