UGUI菜单栏伸缩

UGUI菜单栏伸缩

demo地址,失效了可以找我。。。

http://pan.baidu.com/s/1hs1evFu

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ElasticTest : MonoBehaviour
{
    public List<GameObject> allObj = new List<GameObject>();//所有的父菜单
    Vector2 contentSizedata;//每次更改都需要计算content所容纳的数量
    RectTransform contentRt;
    GameObject lastObj;//最后一次点击的父菜单
    void Start()
    {
        List<GameObject> child = new List<GameObject>();//

        child.Add(GameObject.Find("材料管理 (1)"));
        child.Add(GameObject.Find("材料管理 (2)"));
        child.Add(GameObject.Find("材料管理 (3)"));
        child.Add(GameObject.Find("材料管理 (4)"));
        child.Add(GameObject.Find("材料管理 (5)"));
        AddItem(GameObject.Find("材料管理"), child);

        child.Add(GameObject.Find("材料计划 (1)"));
        child.Add(GameObject.Find("材料计划 (2)"));
        child.Add(GameObject.Find("材料计划 (3)"));
        AddItem(GameObject.Find("材料计划"), child);

        child.Add(GameObject.Find("材料入库 (1)"));
        child.Add(GameObject.Find("材料入库 (2)"));
        AddItem(GameObject.Find("材料入库"), child);

        child.Add(GameObject.Find("材料出库 (1)"));
        child.Add(GameObject.Find("材料出库 (2)"));
        child.Add(GameObject.Find("材料出库 (3)"));
        child.Add(GameObject.Find("材料出库 (4)"));
        child.Add(GameObject.Find("材料出库 (5)"));
        child.Add(GameObject.Find("材料出库 (6)"));
        child.Add(GameObject.Find("材料出库 (7)"));
        AddItem(GameObject.Find("材料出库"), child);

        Init();
    }
    /// <summary>
    /// 初始化
    /// </summary>
    void Init()
    {
        lastObj = null;
        contentRt = GameObject.Find("Canvas/Scroll View/Viewport/Content").GetComponent<RectTransform>();
        contentSizedata = contentRt.sizeDelta;
        contentSizedata.y = 0;
        for (int i = 0; i < allObj.Count; i++)
        {
            ChildListState(allObj[i], 0, false);
            contentSizedata.y += allObj[i].GetComponent<RectTransform>().sizeDelta.y;
        }
        contentRt.sizeDelta = contentSizedata;
    }
    /// <summary>
    /// 加入一个父菜单和子菜单
    /// </summary>
    /// <param name="parent">父菜单物体</param>
    /// <param name="childList">子菜单</param>
    private void AddItem(GameObject parent, List<GameObject> childList)
    {
        parent.GetComponent<Button>().onClick.AddListener(delegate { OnClickParent(parent); });
        allObj.Add(parent);
        ItemGroup group = parent.AddComponent<ItemGroup>();
        foreach (GameObject item in childList)
            group.childList.Add(item);
        childList.Clear();
    }
    /// <summary>
    /// 控制子菜单的显示和隐藏
    /// </summary>
    /// <param name="item">父菜单物体</param>
    /// <param name="isShow">是否显示,0隐藏1显示2列表的第一个物体的相反状态</param>
    /// <param name="costSizedata">是否计算sizedata的高度</param>
    public void ChildListState(GameObject item, int isShow, bool costSizedata = false)
    {
        List<GameObject> childlist = item.GetComponent<ItemGroup>().childList;
        if (isShow == 2 && childlist.Count > 0)
        {
            isShow = childlist[0].activeSelf == false ? 1 : 0;
        }
        for (int i = 0; i < childlist.Count; i++)
        {
            childlist[i].SetActive(isShow == 1 ? true : false);
            if (costSizedata)
            {
                if (childlist[i].activeSelf)
                    contentSizedata.y += childlist[i].GetComponent<RectTransform>().sizeDelta.y;
                else
                    contentSizedata.y -= childlist[i].GetComponent<RectTransform>().sizeDelta.y;
            }
            childlist[i].GetComponentInChildren<Text>().text = item.name + i;
        }
        contentRt.sizeDelta = contentSizedata;
    }
    /// <summary>
    /// 点击父菜单的时候弹出子菜单
    /// </summary>
    /// <param name="item">父菜单物体</param>
    public void OnClickParent(GameObject item)
    {
        ChildListState(item, 2, true);

        if (lastObj != null)
        {
            if (lastObj != item)
            {
                if (lastObj.GetComponent<ItemGroup>().childList[0].activeSelf)
                    ChildListState(lastObj, 2, true);
            }
        }
        lastObj = item;
    }
}

改良版本

**注释已经很详细了,demo也在开头有地址**
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ElasticTest : MonoBehaviour
{
    [System.Serializable]
    public class ChildList
    {
        public GameObject parent;
        public List<GameObject> child;
    }
    List<GameObject> allGroup = new List<GameObject>();//所有的父菜单
    Vector2 contentSizedata;//每次更改都需要计算content所容纳的数量
    RectTransform contentRt;
    GameObject lastObj;//最后一次点击的父菜单
    Vector2 oriPosition;
    public List<ChildList> itemList = new List<ChildList>();
    void Start()
    {
        List<GameObject> child = new List<GameObject>();//

        for (int i = 0; i < itemList.Count; i++)
        {
            AddItem(itemList[i].parent, itemList[i].child);
            if (i == 0)
                oriPosition = itemList[i].parent.GetComponent<RectTransform>().localPosition;
        }
        Init();
    }
    /// <summary>
    /// 初始化
    /// </summary>
    void Init()
    {
        lastObj = null;
        contentRt = GameObject.Find("Canvas/Panel/Scroll View/Viewport/Content").GetComponent<RectTransform>();
        for (int i = 0; i < allGroup.Count; i++)
        {
            ChildListState(allGroup[i], 0);
        }
        CostContentSize();
    }
    /// <summary>
    /// 加入一个父菜单和子菜单
    /// </summary>
    /// <param name="parent">父菜单物体</param>
    /// <param name="childList">子菜单</param>
    private void AddItem(GameObject parent, List<GameObject> childList)
    {
        parent.GetComponent<Button>().onClick.AddListener(delegate { OnClickParent(parent); });
        allGroup.Add(parent);
        ItemGroup group = parent.AddComponent<ItemGroup>();
        foreach (GameObject item in childList)
            group.childList.Add(item);
    }
    /// <summary>
    /// 控制子菜单的显示和隐藏
    /// </summary>
    /// <param name="item">父菜单物体</param>
    /// <param name="isShow">是否显示,0隐藏1显示2列表的第一个物体的相反状态</param>
    void ChildListState(GameObject item, int isShow)
    {
        List<GameObject> childlist = item.GetComponent<ItemGroup>().childList;
        if (isShow == 2 && childlist.Count > 0)
        {
            isShow = childlist[0].activeSelf == false ? 1 : 0;
        }
        for (int i = 0; i < childlist.Count; i++)
        {
            childlist[i].SetActive(isShow == 1 ? true : false);
            childlist[i].GetComponentInChildren<Text>().text = childlist[i].name;
        }
    }
    List<GameObject> allObj = new List<GameObject>();
    List<float> allPos = new List<float>();
    float allChildHeight;
    bool isCanClick = true;
    /// <summary>
    /// 点击父菜单的时候弹出子菜单
    /// </summary>
    /// <param name="item">父菜单物体</param>
    void OnClickParent(GameObject item)
    {
        if (!isCanClick)
        {
            Debug.Log("点击过快");
            return;
        }
        else
        {
            Debug.Log("开始");
        }
        if (lastObj != null)
        {
            if (lastObj != item)
            {
                Debug.Log("点击的不是同一个lastObj", lastObj);
                Debug.Log("点击的不是同一个item", item);
                MoveToTarget(lastObj, false, true);
                MoveToTarget(item, true);
            }
            else
            {
                if (item.transform.Find("Content").GetChild(0).gameObject.activeSelf)
                {
                    Debug.Log("有一级展开,是自己,收回");
                    MoveToTarget(item, false);
                }
                else
                {
                    Debug.Log("有一级展开,是自己,展开");
                    MoveToTarget(item, true);
                }
            }
        }
        else
        {
            Debug.Log("第一次点击");
            MoveToTarget(item, true);
        }
        lastObj = item;
    }
    /// <summary>
    /// 移动一个列表的物体
    /// </summary>
    /// <param name="item">父菜单对象</param>
    /// <param name="isDown">是否收回</param>
    /// <param name="isLast">是否收回子物体</param>
    private void MoveToTarget(GameObject item, bool isDown, bool isLast = false)
    {
        allObj.Clear();//初始化
        allPos.Clear();
        allChildHeight = 0;//展开的所有子物体的高度
        for (int i = 0; i < allGroup.Count; i++)
        {
            if (item == allGroup[i])//当前点击的对象
            {
                //新的子物体的Y=初始Y+子物体的索引*子物体的高度+前边所有的子物体的高度(由于是负数所以表达式里省略了+号)
                allPos.Add(oriPosition.y - i * allGroup[i].GetComponent<RectTransform>().sizeDelta.y - allChildHeight);
                allObj.Add(allGroup[i]);
                RectTransform rt = allGroup[i].GetComponent<RectTransform>();
                List<GameObject> list = allGroup[i].GetComponent<ItemGroup>().childList;
                if (list.Count > 0)//有些菜单可能没有子菜单
                {
                    for (int j = 0; j < list.Count; j++)
                    {
                        ReversalGameObject(list[j]);
                        if (list[j].activeSelf)
                        {
                            allChildHeight += list[j].GetComponent<RectTransform>().sizeDelta.y;
                            allObj.Add(list[j]);
                            allPos.Add(-list[j].GetComponent<RectTransform>().sizeDelta.y - list[j].GetComponent<RectTransform>().sizeDelta.y * j);
                        }
                    }
                }
            }
            else
            {
                if (isLast)
                    continue;
                RectTransform rt = allGroup[i].GetComponent<RectTransform>();
                List<GameObject> list = allGroup[i].GetComponent<ItemGroup>().childList;
                if (lastObj == allGroup[i] && list.Count > 0)
                {
                    if (lastObj.GetComponent<ItemGroup>().childList[0].activeSelf)
                    {
                        Debug.Log("dd");
                        for (int j = 0; j < list.Count; j++)
                        {
                            ReversalGameObject(list[j], 2);//确保上一个菜单已经关闭
                        }
                    }
                }
                //新的父物体的Y=初始Y+父物体的索引*父物体的高度+前边所有的子物体的高度(由于是负数所以表达式里省略了+号)
                allObj.Add(allGroup[i]);
                allPos.Add(oriPosition.y - i * allGroup[i].GetComponent<RectTransform>().sizeDelta.y - allChildHeight);
            }
        }
        StartCoroutine(SetObjectsPosition(isDown));//多个协程嵌套,保证以最少的时间完成任务并加强体验
    }

    void ReversalGameObject(GameObject obj, int state = 0)//0反转1显示 2隐藏
    {
        if (state == 0)
            obj.SetActive(!obj.activeSelf);
        else
            obj.SetActive(state == 1 ? true : false);
    }
    private IEnumerator SetObjectsPosition(bool isDown)
    {
        isCanClick = false;
        GameObject[] game = allObj.ToArray();//由于是引用对象,加上协程,有时候协程没执行完却又执行到这里就会出现差错,所以在这里重新创建并赋值
        float[] ff = allPos.ToArray();
        yield return StartCoroutine(Wait(isDown));

        isCanClick = true;
        Debug.Log("finish");
        CostContentSize();
    }
    private IEnumerator Wait(bool isDown)
    {
        GameObject[] game = allObj.ToArray();//由于是引用对象,加上协程,有时候协程没执行完却又执行到这里就会出现差错,所以在这里重新创建并赋值
        float[] ff = allPos.ToArray();
        for (int i = 0; i < game.Length; i++)
        {
            if (isDown)
                StartCoroutine(GoToPointDownItem(game[i], ff[i]));
            else
                StartCoroutine(GoToPointUpItem(game[i], ff[i]));
        }
        yield return null;
    }

    float shiftY = 20;//渐变的速度
    IEnumerator GoToPointDownItem(GameObject currentObj, float target)//弹出
    {
        RectTransform rt = currentObj.GetComponent<RectTransform>();
        Vector2 pos = rt.localPosition;
        while (pos.y > target)
        {
            pos.y -= shiftY;
            rt.localPosition = pos;
            yield return null;
        }
        currentObj.GetComponent<RectTransform>().localPosition = new Vector2(currentObj.GetComponent<RectTransform>().localPosition.x, target);
    }
    IEnumerator GoToPointUpItem(GameObject currentObj, float target)//收回
    {
        RectTransform rt = currentObj.GetComponent<RectTransform>();
        Vector2 pos = rt.localPosition;
        while (pos.y < target)
        {
            pos.y += shiftY;
            rt.localPosition = pos;
            yield return null;
        }
        currentObj.GetComponent<RectTransform>().localPosition = new Vector2(currentObj.GetComponent<RectTransform>().localPosition.x, target);
    }
    void CostContentSize()//计算content的可视范围
    {
        float allItemHeight = 0;
        for (int i = 0; i < allGroup.Count; i++)
        {
            allItemHeight += allGroup[i].GetComponent<RectTransform>().sizeDelta.y;
            List<GameObject> list = allGroup[i].GetComponent<ItemGroup>().childList;
            if (list.Count > 0)
            {
                for (int j = 0; j < list.Count; j++)
                {
                    if (!list[j].activeSelf)
                        continue;
                    allItemHeight += list[j].GetComponent<RectTransform>().sizeDelta.y;
                }
            }
        }
        float paddingTop = 20;
        contentSizedata.y = allItemHeight;
        contentSizedata.y += paddingTop;
        contentRt.sizeDelta = contentSizedata;
    }
}
using System.Collections.Generic;
using UnityEngine;

public class ItemGroup : MonoBehaviour
{
    public List<GameObject> childList = new List<GameObject>();
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值