效果图:
代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class ParentMenu : MonoBehaviour { private GameObject childMenu;//子菜单的parent private RectTransform[] childs;//所有子菜单的rect private RectTransform itemRect;//子菜单的prefab private Vector3 offset;//单个子菜单的高度 private int count;//子菜单的个数 public bool isOpening { get; private set; }//父菜单是否展开 public bool isCanClick { get; set; }//父菜单是否可以点击 public void Init(RectTransform rect, int count) { childMenu = transform.Find("childMenu").gameObject; itemRect = rect; this.count = count; childs = new RectTransform[this.count]; offset = new Vector3(0, itemRect.rect.height); for (int i = 0; i < this.count; i++) { childs[i] = Instantiate(itemRect, childMenu.transform); } childMenu.gameObject.SetActive(false); isOpening = false; isCanClick = true; GetComponent<Button>().onClick.AddListener(OnButtonClick); } void OnButtonClick() { if (!isCanClick) return; if (!isOpening) StartCoroutine(ShowChildMenu()); else StartCoroutine(HideChildMenu()); } IEnumerator ShowChildMenu() { childMenu.gameObject.SetActive(true); for (int i = 0; i < count; i++) { childs[i].localPosition -= i * offset; yield return new WaitForSeconds(0.1f); } isCanClick = true; isOpening = true; } IEnumerator HideChildMenu() { for (int i = count - 1; i >= 0; i--) { childs[i].localPosition += i * offset; yield return new WaitForSeconds(0.1f); } childMenu.gameObject.SetActive(false); isCanClick = true; isOpening = false; } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class FoldableMenu : MonoBehaviour { private RectTransform content;//父物体的parent private TextAsset textAsset;//所有菜单信息 private RectTransform parentRect;//父菜单的prefab private RectTransform[] parentArr;//所有父菜单的数组 private RectTransform childRect;//子菜单的prefab private Vector3 parentOffset;//单个父菜单的高度 private Vector3 childOffset;//单个子菜单的高度 private int[] cntArr;//所有父菜单拥有的子菜单个数 void Awake() { Init(); } void Init() { content = transform.Find("Viewport/Content").GetComponent<RectTransform>(); textAsset = Resources.Load<TextAsset>("menuInfo"); parentRect = Resources.Load<RectTransform>("parentMenu"); parentOffset = new Vector3(0, parentRect.rect.height); childRect = Resources.Load<RectTransform>("item"); childOffset = new Vector3(0, childRect.rect.height); var info = textAsset.text.Split(',');//获取子菜单个数信息 cntArr = new int[info.Length]; parentArr = new RectTransform[info.Length]; //初始化content高度 content.sizeDelta = new Vector2(content.rect.width, parentArr.Length * parentRect.rect.height); for (int i = 0; i < cntArr.Length; i++) { parentArr[i] = Instantiate(parentRect, content.transform); parentArr[i].localPosition -= i * parentOffset; cntArr[i] = int.Parse(info[i]); parentArr[i].GetComponent<ParentMenu>().Init(childRect, cntArr[i]); int j = i; parentArr[i].GetComponent<Button>().onClick.AddListener(() => { OnButtonClick(j); }); } } void OnButtonClick(int i) { if (!parentArr[i].GetComponent<ParentMenu>().isCanClick) return; parentArr[i].GetComponent<ParentMenu>().isCanClick = false; if (!parentArr[i].GetComponent<ParentMenu>().isOpening) StartCoroutine(MenuDown(i)); else StartCoroutine(MenuUp(i)); } IEnumerator MenuDown(int index) { for (int i = 0; i < cntArr[index]; i++) { //更新content高度 content.sizeDelta = new Vector2(content.rect.width, content.rect.height + childOffset.y); for (int j = index + 1; j < parentArr.Length; j++) { parentArr[j].localPosition -= childOffset; } yield return new WaitForSeconds(0.1f); } } IEnumerator MenuUp(int index) { for (int i = 0; i < cntArr[index]; i++) { //更新content高度 content.sizeDelta = new Vector2(content.rect.width, content.rect.height - childOffset.y); for (int j = index + 1; j < parentArr.Length; j++) { parentArr[j].localPosition += childOffset; } yield return new WaitForSeconds(0.1f); } } }