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; } }