zoukankan      html  css  js  c++  java
  • 糍粑大叔的独游之旅-u3d实现弹出菜单(上)-动态列表

    在u3d5.x中,使用ugui作为默认的界面系统,但控件实在太少,很多需求都不能满足,比如弹出菜单(PopupMenu)

    我也懒得去网上找现成的实现,再加上现有代码已经有很多有关列表控件的功能,不想再重新动这些代码。

    所以自己实现一个,目前先只实现核心、搭建控件相关类的骨干,后期再慢慢丰富和做的更花哨。

    开篇之前声明,我的u3d理解非常有限,有很多也许本身自带的功能或有现成库功能我不知道,所以选择了自己探索或实现,

    感觉太low欢迎给出好的意见。

    定义和代码结构

    PopupMenu是点击鼠标或按钮后,在相应位置弹出的一个列表控件。

    这个列表拥有子列表,点击或鼠标进入某个列表项后,将弹出子列表。

    子列表本身也是一个PopupMenu,也可以有拥有子列表。

    由这个定义可以看出:

    1、PopupMenu首先需要列表控件的支持,但ugui的ScrollView支持不够,所以需要动态列表的支持。

    2、其次列表项需要支持点击或进入事件,点击Click事件,ugui的button是支持的;鼠标进入PointEnter事件,不支持。所有需要一个扩展按钮实现进入事件的响应,这是可选项。

    3、每个列表项需要有特殊标识,或者要装载一份部分数据,至少有不同的点击或进入响应函数,这需要需要一类去实现,即列表项。

    4、需要一个类实现弹出、隐藏、创建列表、调整位置等弹出菜单的功能,这个类就是弹出菜单的组件。

     

    动态列表

    动态列表是让ugui的ScrollView支持动态添加、删除列表项的类。我的代码命名为ViewList,关键需要实现动态创建列表项和调整ContentSize的功能。

    这里创建一个自有文本信息的列表项:

       public ListViewItem CreateTextButton(string itemName )
        {
            GameObject prototype = Resources.Load<GameObject>("GUI/Control/ItemTextButton");
            GameObject button = GameObject.Instantiate(prototype);
    
            button.transform.SetParent(viewContent.transform);
            button.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
            button.name = prototype.name + "_" + itemName;
    
            Text text = button.transform.Find("Text").GetComponent<Text>();
            text.color = new Color(0xa9 / 255f, 0xdd / 255f, 0xfd / 255f);
            text.text = itemName;
    
            ListViewItem i = button.GetComponent<ListViewItem>();
            if (i == null)
                i = button.AddComponent<ListViewItem>();
            i.listView = this;
            m_Items.Add(i);
    
            _ResizeVerticalContent(button);
            return i;
        }

    其中ListViewItem是列表项,将所有item记录到m_Items,便于PopupMenu里操作。

    viewContent是列表项的父节点,支持ScrollRect也支持不使用ScrollRect:

      if (GetComponent<ScrollRect>())
            viewContent = GetComponent<ScrollRect>().content.gameObject;
        else
            viewContent = gameObject;

    下面代码实现对垂直布局的content的大小控制。

        void _ResizeVerticalContent( GameObject button)
        {
            float height = button.GetComponent<LayoutElement>().minHeight;
            float spacing = viewContent.GetComponent<VerticalLayoutGroup>().spacing;
            float tb = viewContent.GetComponent<VerticalLayoutGroup>().padding.top;
            viewContent.GetComponent<RectTransform>().sizeDelta = 
                new Vector2(viewContent.GetComponent<RectTransform>().sizeDelta.x,
                    m_Items.Count * (spacing + height) - spacing + tb);
        }

    控制content的大小很重要,对于ScrollView来说,content放下所有列表项,对Viewport设置mask,content的长度(就垂直滚动而言)远远大于Viewport,只显示viewport大小范围内的

    content,从而实现滚动效果。对于非ScrollView,即将自身但做列表项的容器,不存在滚动效果,自身的大小需要和列表项的个数相契合。

    如果是Grid布局的,可以参考下面的代码:

            float height = button.GetComponent<LayoutElement> ().minHeight;
            float spacing = viewContent.GetComponent<GridLayoutGroup> ().spacing.y;
            int NC = (int)(viewContent.GetComponent<RectTransform> ().sizeDelta.x /
                button.GetComponent<LayoutElement> ().minWidth);
    
            viewContent.GetComponent<RectTransform> ().sizeDelta = 
                new Vector2 (viewContent.GetComponent<RectTransform> ().sizeDelta.x,
                    (viewContent.transform.childCount % NC == 0 ?
                        viewContent.transform.childCount / NC :
                        viewContent.transform.childCount / NC + 1) 
                    * (float)(spacing + height));

    下篇将介绍扩展按钮、ViewListItem等

  • 相关阅读:
    【JDK】:java.lang.Integer源码解析
    使用truelicense实现用于JAVA工程license机制(包括license生成和验证)
    Android Button.getWidth()为0的问题
    nacos启动报错nacos Unable to start web server;
    Oracle字符集相关学习笔记记录
    Oracle触发器简单使用记录
    Oracle分析函数、窗口函数简单记录汇总
    Oracle远程数据建物化视图(materialized)创建简单记录,以及DBLINK的创建
    Oracle 行列转换函数pivot、unpivot的使用(二)
    Oracle递归查询(start with…connect by prior)
  • 原文地址:https://www.cnblogs.com/uncleciba/p/5730731.html
Copyright © 2011-2022 走看看