【UGUI】踩坑填坑——DropDown

在使用UGUI的 DropDown 时, Canvas 的 Render Mode 选择了 Screen Space--Camera, 此时遇到一个小bug, 当我把这个下拉组件放到屏幕中间附近时, 下拉列表显示是正常的。当我把组件整体移到边缘,突然出现下拉列表的 Content 的坐标 不合法,由于 ugui 的点击关闭处理是在 Canvas 的子节点最下方又生成一个 全屏的 遮罩 来保证实现 "点击关闭",所以此时整个界面卡死..........翻遍源码断点我也没找到问题..

【UGUI】踩坑填坑——DropDown_第1张图片中间:边缘【UGUI】踩坑填坑——DropDown_第2张图片【UGUI】踩坑填坑——DropDown_第3张图片


另外,他的下拉列表实现, 不适合多个数据,假如有百十个就生成百十个下来的子菜单,这明显是不合理的,所以,把下拉改成 无限循环 列表是必须的。

于是,开始自己动手造轮子:

using System;
using System.Collections;
using System.Collections.Generic;
using Assets.UI;
using UnityEngine;
using UnityEngine.UI;

/// 
/// Introduction: GDropDown
/// Author: 	Cheng
/// Time: 
/// 
[AddComponentMenu("UI/GDropdown", 100)]
[RequireComponent(typeof(RectTransform))]
public class GDropDown : MonoBehaviour
{

    [Tooltip("Button of Whole Component")]
    [SerializeField]
    private Toggle m_CaptionToggle;
    /// 
    /// Button of Whole Component
    /// 
    public Toggle CaptionToggle { get { return m_CaptionToggle; } set { SetCaptionButton(value);} }

    [Tooltip("Display Text of Selected Item")]
    [SerializeField]
    private Text m_CaptionText;
    /// 
    /// Display Text of Selected Item
    /// 
    public Text CaptionText { get { return m_CaptionText; } set { m_CaptionText = value; } }

    [Tooltip("Display Image of Selected Item")]
    [SerializeField]
    private Image m_CaptionImage;
    /// 
    /// Display Image of Selected Item
    /// 
    public Image CaptionImage { get { return m_CaptionImage; } set { m_CaptionImage = value; } }

    [Space]

    [Tooltip("Drop List")]
    [SerializeField]
    private ScrollRect m_ScrollRect;
    /// 
    /// Drop List 
    /// 
    public ScrollRect ScrollRect { get { return m_ScrollRect; } set { m_ScrollRect = value; } }

    [Tooltip("Template of Drop List's Item")]   
    [SerializeField]
    private GameObject m_DropItem;
    /// 
    /// Template of Drop List's Item
    /// 
    public GameObject DropItem { get { return m_DropItem; } set { SetDropItem(value); } }

    [Tooltip("Current Select Index")]
    [SerializeField]
    private int m_Index;
    /// 
    /// Current Select Index
    /// 
    public int Index { get { return m_Index; } set { SetSelectIndex(value); }}
    public string Text { get { return m_DropData.Count > Index ? m_DropData[Index].text : ""; } }

    /// 
    /// Drop Down Value Changed
    /// 
    public Callback_1 OnValueChanged;

    [Tooltip("Drop Data")]
    [SerializeField]
    List m_DropData = new List();

    private ScrollList m_ScrollList;
    private Dictionary m_Items = new Dictionary();
    private RectTransform m_PointerMask;
    private Transform m_Canvas;
    

    void Awake()
    {
        m_ScrollList = GetOrAddComponent(ScrollRect.gameObject);
        m_ScrollList.onItemRender = OnItemRender;
        SetSelectIndex(m_Index);
        SetDropItem(m_DropItem);
        RefreshShowValue();
        SetCaptionButton(m_CaptionToggle);

        m_CaptionToggle.isOn = false;
        CloseMask();
    }

    public void AddOptions(string[] options)
    {
        for (int i = 0; i < options.Length; i++)
            this.m_DropData.Add(new GItemData(options[i]));

        if (m_CaptionToggle.isOn)
            OpenMask();
    }

    public void AddOptions(Sprite[] options)
    {
        for (int i = 0; i < options.Length; i++)
            this.m_DropData.Add(new GItemData(options[i]));

        if (m_CaptionToggle.isOn)
            OpenMask();
    }

    public void AddOptions(GItemData[] options)
    {
        for (int i = 0; i < options.Length; i++)
            this.m_DropData.Add(options[i]);

        if (m_CaptionToggle.isOn)
            OpenMask();
    }

    public void RemoveAt(int index)
    {
        if (this.m_DropData.Count > index)
        {
            this.m_DropData.RemoveAt(index);
            if (index == Index)
            {
                SetSelectIndex(index-1);
            }
        }
    }

    public void ClearOptions()
    {
        this.m_DropData.Clear();
        if (m_CaptionToggle.isOn)
            OpenMask();
    }


    /// 
    /// Refresh Display View
    /// 
    private void RefreshShowValue()
    {
        if (m_DropData.Count > Index)
        {
            GItemData data = m_DropData[Index];
            if (CaptionText != null)
                CaptionText.text = data.text;
            if (CaptionImage != null)
                CaptionImage.sprite = data.image;
        }
        else
        {
            if (CaptionText != null)
                CaptionText.text = "";
            if (CaptionImage != null)
                CaptionImage.sprite = null;
        }
    }

    /// 
    /// Render Item in List
    /// 
    /// 
    /// 
    private void OnItemRender(int index, Transform child)
    {
        GItem item;
        if (!m_Items.TryGetValue(child, out item))
            item = new GItem(this, child);

        if (m_DropData.Count > index)
        {
            item.Reset(m_DropData[index].text, m_DropData[index].image, index == Index);
        }
    }

    /// 
    /// Set Cur Select Index When Click
    /// 
    /// 
    internal void SetSelectIndex(int p)
    {
        if (p < m_DropData.Count) //if exist data
        {
            m_Index = p;
            RefreshShowValue();
            if (OnValueChanged != null)
            {
                OnValueChanged(m_Index);
            }
        }
        else
        {
            if (m_DropData.Count > 0)//Back To First
            {
                m_Index = 0;
                RefreshShowValue();
                if (OnValueChanged != null)
                {
                    OnValueChanged(m_Index);
                }
            }
        }

        foreach (var value in m_Items.Values)
        {
            value.SetActive(false);
        }
        m_CaptionToggle.isOn = false;
    }

    /// 
    /// Open Mask to Poniters Out of List
    /// 
    private void OpenMask()
    {
        if (m_PointerMask == null)//Create Mask
        {
            GameObject o = new GameObject("Pointer Mask");
            o.transform.SetParent(transform);
            Image mask = o.AddComponent();
            mask.color = new Color(1, 1, 1, 0);
            m_PointerMask = o.transform as RectTransform;
            m_PointerMask.sizeDelta = new Vector2(Screen.width, Screen.height);
            Button btnMask = o.AddComponent
【UGUI】踩坑填坑——DropDown_第4张图片


组件的点击由Toggle 来控制 与 系统UGUI的类似,支持 点击选中 图片和文字, 自己添加一个下拉列表。

注意: 下拉子选项中, 命名 “text”的“Text”组件、命名 “image”的“Image”组件为该选项的可填充值,看代码一眼便知。命名“selected”的表示下拉列表打开时该选项选中的表现,与toggle相同,我只是乐意改成了button表示而已


Index 就是当前选中项,无限列表需要用到我以前文章中的一篇【UGUI】无限列表 ScrollView List

你可能感兴趣的:(UGUI)