首页 > 技术文章 > Unity 改写Dropdown支持多次点击同一选项均回调

qq2351194611 2021-12-10 09:55 原文

1.UGUI自带的Dropdown,创建之后,运行场景默认选择第一个选项,再次点击第一个选项也不会触发,因项目需求,所以要改成多次点击有效

 

2.创建下拉框(Dropdown),创建好之后删除Dropdown组件

 

3.创建c#脚本 (重写下拉框,添加一个bool变量用来控制)

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

public class DropdownEx : Dropdown
{
    public bool m_AlwaysCallback = false;
    public  void  ShowController()
    {
        base.Show();
        Transform toggleRoot = transform.Find("Dropdown List/Viewport/Content");
        Toggle[] toggleList = toggleRoot.GetComponentsInChildren<Toggle>(false);
        for (int i = 0; i < toggleList.Length; i++)
        {
            Toggle temp = toggleList[i];
            temp.onValueChanged.RemoveAllListeners();
            temp.isOn = false;
            temp.onValueChanged.AddListener(x => OnSelectItemEx(temp));
        }
    }

    public override void OnPointerClick(PointerEventData eventData)
    {
        ShowController();
    }

    public void OnSelectItemEx(Toggle toggle)
    {
        if (!toggle.isOn)
        {
            toggle.isOn = true;
            return;
        }

        int selectedIndex = -1;
        Transform tr = toggle.transform;
        Transform parent = tr.parent;
        for (int i = 0; i < parent.childCount; i++)
        {
            if (parent.GetChild(i) == tr)
            {
                // Subtract one to account for template child.
                selectedIndex = i - 1;
                break;
            }
        }

        if (selectedIndex < 0)
            return;
        if (value == selectedIndex && m_AlwaysCallback)
            onValueChanged.Invoke(value);
        else
            value = selectedIndex;
        Hide();
    }
}

 

4.把脚本添加到下拉框上面会出现新的组件(如下图所示)

 

箭头处需要自己拖上去

 

5.创建一个Editor脚本放在Editor文件夹下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using UnityEditor.UI;
[CustomEditor(typeof(DropdownEx), true)]
[CanEditMultipleObjects]
public class DropdowmExEditor : DropdownEditor
{
    SerializedProperty m_AlwaysCallback;
    protected override void OnEnable()
    {
        base.OnEnable();
        m_AlwaysCallback = serializedObject.FindProperty("m_AlwaysCallback");
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        EditorGUILayout.PropertyField(m_AlwaysCallback);
        serializedObject.ApplyModifiedProperties();
    }
}

 

需要重复点击就勾选上  m_AlwaysCallback 变量

 

 在加一个脚本方便使用

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class DIO : MonoBehaviour
{
    //private List<string> List_int = new List<string> {"DI1","DI2","DI3","DI4","DI5","DI6","DI7","DI8" };
    public int DIOINT=0;
    [HideInInspector]
    public Dropdown dropdown;
    
    // Start is called before the first frame update
    void Start()
    {
        DIOINT = 1;
        dropdown = this.GetComponent<Dropdown>();
        UpdateDropdownView(DIO_Setting.instance_.List_DI);
        dropdown.onValueChanged.AddListener(Changed);
    }
    private void Changed(int index)
    {
      
        switch (index )
        {
            case 0:
                DIOINT = 1;
                ShuaXin(DIO_Setting.instance_.List_DI[0]);
                DIO_Setting.instance_.List_DI.RemoveAt(0);
                //dropdown.interactable = false;              
                break;
            case 1:
                DIOINT = 2;
                ShuaXin(DIO_Setting.instance_.List_DI[1]);
                DIO_Setting.instance_.List_DI.RemoveAt(1);
                //dropdown.interactable = false;
                break;
            case 2:
                DIOINT = 3;
                ShuaXin(DIO_Setting.instance_.List_DI[2]);
                DIO_Setting.instance_.List_DI.RemoveAt(2);
                //dropdown.interactable = false;
                break;
            case 3:
                DIOINT = 4;
                ShuaXin(DIO_Setting.instance_.List_DI[3]);
                DIO_Setting.instance_.List_DI.RemoveAt(3);
                //dropdown.interactable = false;
                break;
            case 4:
                DIOINT = 5;
                ShuaXin(DIO_Setting.instance_.List_DI[4]);
                DIO_Setting.instance_.List_DI.RemoveAt(4);
                //dropdown.interactable = false;
                break;
            case 5:
                DIOINT = 6;
                ShuaXin(DIO_Setting.instance_.List_DI[5]);
                DIO_Setting.instance_.List_DI.RemoveAt(5);
                //dropdown.interactable = false;
                break;
            case 6:
                DIOINT = 7;
                ShuaXin(DIO_Setting.instance_.List_DI[6]);
                DIO_Setting.instance_.List_DI.RemoveAt(6);
                //dropdown.interactable = false;
                break;
            case 7:
                DIOINT = 8;
                ShuaXin(DIO_Setting.instance_.List_DI[7]);
                DIO_Setting.instance_.List_DI.RemoveAt(7);
                //dropdown.interactable = false;
                break;
           
            default:
                break;
        }
    }
    //默认显示第一条数据
    public void UpdateDropdownView(List<string> showNames)
    {
        //清空下下拉框数据
       this.dropdown.options.Clear();
        Dropdown.OptionData tempData;
        for (int i = 0; i < showNames.Count; i++)
        {
            tempData = new Dropdown.OptionData();
            tempData.text = showNames[i].ToString ();
            dropdown.options.Add(tempData);
        }
        //把第一条数据显示为默认
        dropdown.captionText.text = showNames[0].ToString();

    }
    //更新下拉框数据
    public void UpdateDropdownView_1(List<string> showNames)
    {
        //清空下下拉框数据
        this.dropdown.options.Clear();
        Dropdown.OptionData tempData;
        for (int i = 0; i < showNames.Count; i++)
        {
            tempData = new Dropdown.OptionData();
            tempData.text = showNames[i].ToString();
            dropdown.options.Add(tempData);
        }            
    }
    //下拉框显示选中数据   
    //设置默认数据
    public void ShuaXin(string sows)
    {
        this.dropdown.options.Clear();
        Dropdown.OptionData tempData;
        tempData = new Dropdown.OptionData();
        tempData.text = sows.ToString();
        dropdown.captionText.text = sows.ToString();
        //dropdown.interactable = false;
    }
    private void Update()
    {
        //DIO_Setting.instance_.List_DI  和上面的List_int是一样的  因为要选中一个删除一个,列表要放在
        //其他脚本 所以一直更新列表
        UpdateDropdownView_1(DIO_Setting.instance_.List_DI);
    }

   
}
C#DIO脚本

 

 最后一个实用的技巧

如果你不想下拉框一开始就是选中状态其实也是可以的

 

 如箭头所示改成-1就行了,就是默认不选中

 

 

 

 

❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤

❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤

❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤

 

推荐阅读