using SuperTreeView; using System.Collections.Generic; using System.Xml.Serialization; using UnityEngine; using UnityEngine.UI; using ZXKFramework; namespace DongWuYiXue.DaoNiaoShu { public class TData_R { public List data_1s = new(); } public class TData_1 { public List data_2s = new(); public string name; public string data; } public class TData_2 { public string name; public string data; } public class TreeViewPanel : UIBase { public override string GroupName => "TreeViewPanel"; public override string Name => "TreeViewPanel"; public TreeView mTreeView; int mCurSelectedItemId = 0; UIDynamicMover uIDynamicMover; public ScrollRect scrollRect; //Action onclick; bool isDestroy; public override void Init(IUIManager uictrl) { base.Init(uictrl); scrollRect = transform.FindFirst("TreeScrollView"); mTreeView = transform.FindFirst("TreeView"); uIDynamicMover = transform.FindFirst("arrBtn"); mTreeView.OnItemCustomEvent = OnItemCustomEvent; mTreeView.OnItemExpandBegin = OnItemExpandBegin; mTreeView.OnItemCollapseBegin = OnItemCollapseBegin; } public void BuildButton(TData_R data_R) { //onclick = callBack; mTreeView.InitView(); foreach (var item1 in data_R.data_1s) { TreeViewItem t1 = mTreeView.AppendItem("ItemPrefab1"); t1.GetComponent().SetItemInfo(item1.name, item1.data); foreach (var item2 in item1.data_2s) { TreeViewItem t2 = t1.ChildTree.AppendItem("ItemPrefab2"); t2.GetComponent().SetItemInfo(item2.name, item2.data); } } mTreeView.CollapseAllItem(); } private void OnItemCollapseBegin(TreeViewItem item) { ItemPrefab1 st = item.GetComponent(); st.SetExpandStatus(false); } private void OnItemExpandBegin(TreeViewItem item) { ItemPrefab1 st = item.GetComponent(); st.SetExpandStatus(true); } private void OnItemCustomEvent(TreeViewItem item, SuperTreeView.CustomEvent @event, object arg3) { if (GetModel().modeType == ModeType.KaoHe) return; if (@event == SuperTreeView.CustomEvent.ItemClicked) { Debug.Log(arg3); OnItemSelect(item); Game.Instance.uiManager.ShowUI(); GameManager.Instance.fsm.PlayClip("跳步"); GameManager.Instance.sceneDataHandler.LoadSceneDataFromJson(GetModel().mainData.folder + "/SaveData/" + (string)arg3 + ".json", () => { GameManager.Instance.fsm.ChangeState((string)arg3); Game.Instance.uiManager.CloseUI(); }); } } private void OnItemSelect(TreeViewItem item) { ItemPrefab2 st = item.GetComponent(); if (mCurSelectedItemId > 0) { if (item.ItemId == mCurSelectedItemId) { return; } TreeViewItem curSelectedItem = mTreeView.GetTreeItemById(mCurSelectedItemId); if (curSelectedItem != null) { curSelectedItem.GetComponent().IsSelected = false; } mCurSelectedItemId = 0; } st.IsSelected = true; mCurSelectedItemId = item.ItemId; } public void Locate(string name1, string name2) { mTreeView.CollapseAllItem(); ItemPrefab1[] itemPrefab1s = mTreeView.GetComponentsInChildren(); ItemPrefab1 itemPrefab1 = null; for (int i = 0; i < itemPrefab1s.Length; i++) { if (itemPrefab1s[i].TextName.text == name1) { Nevigate(itemPrefab1s[i].GetComponent()); itemPrefab1s[i].GetComponent().Expand(); itemPrefab1s[i].IsSelected = true; itemPrefab1 = itemPrefab1s[i]; } } if (itemPrefab1 != null) { ItemPrefab2[] itemPrefab2s = itemPrefab1.GetComponentsInChildren(); for (int i = 0; i < itemPrefab2s.Length; i++) { if (itemPrefab2s[i].TextName.text == name2) { OnItemSelect(itemPrefab2s[i].GetComponent()); } } } //Nevigate(itemPrefab1s[i].GetComponent()); } public void Nevigate(RectTransform item) { // InverseTransformPoint: Transforms position from world space to local space, 和TransformPoint左右相反 // 这步的意义是把 item、viewport的localPosition转换到同一个父节点下,才能计算出需要移动的差值 // 看图1 Vector3 itemCurrentLocalPostion = scrollRect.GetComponent().InverseTransformPoint(ConvertLocalPosToWorldPos(item)); Vector3 itemTargetLocalPos = scrollRect.GetComponent().InverseTransformPoint(ConvertLocalPosToWorldPos(scrollRect.viewport)); // 计算需要移动的距离 Vector3 diff = itemTargetLocalPos - itemCurrentLocalPostion; // 当第一个item处于viewport最上时 verticalNormalizedPosition = 0,处于最左时 horizontalNormalizedPosition = 0,看图2 // 计算需要移动的距离占的比,即需要移动的距离占可移动长度的百分比,看图3 // 如果你的 viewport 中只能显示一个item的话,这样就行了,但是超过了1个的话需要计算偏移: // 以数值方向为例,当verticalNormalizedPosition = 0,第一个 item 距离 viewport的中心位置其实有一段距离的, // 所以要减去这段距离,diff.y - offset,再计算 newNormalizedPosition,看图4 var newNormalizedPosition = new Vector2( diff.x / (scrollRect.content.GetComponent().rect.width - scrollRect.viewport.rect.width), diff.y / (scrollRect.content.GetComponent().rect.height - scrollRect.viewport.rect.height) ); // 当时 normalizedPosition - 需要移动的占比newNormalizedPosition,得到最终的位置normalizedPosition newNormalizedPosition = scrollRect.GetComponent().normalizedPosition - newNormalizedPosition; newNormalizedPosition.x = Mathf.Clamp01(newNormalizedPosition.x); newNormalizedPosition.y = Mathf.Clamp01(newNormalizedPosition.y); // 也可以只设置水平方向 horizontalNormalizedPosition,或竖直方向 verticalNormalizedPosition // 设置 normalizedPosition 等于同时设置 horizontalNormalizedPosition, verticalNormalizedPosition // normalizedPosition.x == horizontalNormalizedPosition // normalizedPosition.y == verticalNormalizedPosition // normalizedPosition == new Vector2(horizontalNormalizedPosition, verticalNormalizedPosition) scrollRect.GetComponent().normalizedPosition = newNormalizedPosition; // 如果有分类功能,比如点击type1,scrollview中显示type1中的数据,点击type2,scrollview中显示type2中的数据,需要在给 // normalizedPosition 赋值前先赋值 (0, 0),否则最后一行代码获取的 normalizedPosition 还是上一类型 type 中的 // normalizedPosition,导致出bug } // 这个方法的作用是消除Pivot数值的影响,Pivot不是(0.5,0.5)时,最后所计算出来的结果会有误差 // 如果是(0.5, 0.5)的话可以直接返回 target.parent.TransformPoint(localPosition) private Vector3 ConvertLocalPosToWorldPos(RectTransform target) { var pivotOffset = new Vector3( (0.5f - target.pivot.x) * target.rect.size.x, (0.5f - target.pivot.y) * target.rect.size.y, 0f); var localPosition = target.localPosition + pivotOffset; // TransformPoint: Transforms position from local space to world space return target.parent.TransformPoint(localPosition); } public void LockAllBtn() { //ItemPrefab1[] itemPrefab1s = mTreeView.GetComponentsInChildren(true); //for (int i = 0; i < itemPrefab1s.Length; i++) //{ // itemPrefab1s[i].LockClick(); //} ItemPrefab2[] itemPrefab2s = mTreeView.GetComponentsInChildren(true); for (int i = 0; i < itemPrefab2s.Length; i++) { itemPrefab2s[i].LockClick(); } } public void UnLockAllBtn() { if (mTreeView == null) return; ItemPrefab2[] itemPrefab2s = mTreeView.GetComponentsInChildren(true); for (int i = 0; i < itemPrefab2s.Length; i++) { itemPrefab2s[i].UnlockClick(); } } private void OnDestroy() { isDestroy = true; } } }