编辑器扩展(一)Dropdown有不可选的选项

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/darkrabbit/article/details/79163111

有不可选选项的Dropdown

前几日群里的小伙伴问道,如何让Dropdown下的选项不可选(变成灰色)。
最初直接想的是把ToggleInteractable设置成false就好了。
可是发现Unity的Dropdown没法获取物体。
好吧,我们可以用GetChild()方法进去找子物体的Toggle,可是太麻烦了。
所以干脆就变成做个编辑器扩展。

完成后的设置
DRDropdown

  • 其中Default Disable Options,就是在创建列表的时候默认为不可选的Index

完成后的截图
DRDropdown

在创建时,用Unity的Dropdown创建,然后删除Unity的Dropdown,再添加这个脚本。

Dropdown代码:

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

[AddComponentMenu("UI/DR DropDown")]
[RequireComponent(typeof(Image))]
public class DRDropDown : Dropdown
{
    /// <summary>
    /// 在添加Item时,不可用的Index,如果是动态添加的不同列表,可以在打开之前这个里改变值
    /// </summary>
    [SerializeField]
    [HideInInspector]
    private List<int> m_DefaultDisables = new List<int>();
    public List<int> disables
    {
        get { return m_DefaultDisables; }
    }

    /// <summary>
    /// 保存的Toggle
    /// </summary>
    private List<Toggle> m_ItemToggles = new List<Toggle>();

    /// <summary>
    /// 列表打开状态时,可以获取Toggle,可改变Interactable动态修改是否可选
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public Toggle GetItemToggle(int index)
    {
        if (index < 0 || index >= m_ItemToggles.Count)
        {
            return null;
        }
        return m_ItemToggles[index];
    }

    public DRDropDown() : base()
    {

    }

    protected override void Awake()
    {
        base.Awake();

        if (template == null)
        {
            Transform tran = transform.Find("Template")
            if (tran != null)
            {
                template = tran as RectTransform;
            }
        }

        if (captionText == null)
        {
            Transform tran = transform.Find("Label");
            if (tran != null)
            {
                captionText = tran.GetComponent<Text>();
            }
        }

        if (itemText == null)
        {
            Transform tran = transform.Find("Template/Viewport/Content/Item/Item Label");
            if (tran != null)
            {
                itemText = tran.GetComponent<Text>();
            }
        }

    }

    /// <summary>
    /// 打开列表时,创建Item的Callback
    /// </summary>
    /// <param name="itemTemplate"></param>
    /// <returns></returns>
    protected override DropdownItem CreateItem(DropdownItem itemTemplate)
    {
        DropdownItem item = base.CreateItem(itemTemplate);

        // 添加Toggle
        m_ItemToggles.Add(item.toggle);

        // 根据Index设置是否可选
        int index = m_ItemToggles.Count - 1;
        for (int i = 0; i < m_DefaultDisables.Count; i++)
        {
            if (index == m_DefaultDisables[i])
            {
                item.toggle.interactable = false;
                break;
            }
        }

        return item;
    }

    /// <summary>
    /// 关闭列表时,销毁Item的Callback
    /// </summary>
    /// <param name="item"></param>
    protected override void DestroyItem(DropdownItem item)
    {
        // 如果包含Toggle,就删除
        if (m_ItemToggles.Contains(item.toggle))
        {
            m_ItemToggles.Remove(item.toggle);
        }

        base.DestroyItem(item);
    }
}

Editor代码如下:

using UnityEngine;
using UnityEngine.UI;

#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
using UnityEditor.UI;
#endif

#if UNITY_EDITOR
[CanEditMultipleObjects]
[CustomEditor(typeof(DRDropDown), true)]
public class DRDropDownEditor : DropdownEditor
{
    private ReorderableList m_List;

    public DRDropDown drop
    {
        get { return target as DRDropDown; }
    }

    protected override void OnEnable()
    {
        base.OnEnable();

        ReCreateList();
    }

    /// <summary>
    /// 创建m_DefaultDisables的ReorderableList
    /// </summary>
    private void ReCreateList()
    {
        m_List = new ReorderableList(serializedObject, serializedObject.FindProperty("m_DefaultDisables"), true, true, true, true);

        m_List.drawHeaderCallback = (Rect rect) =>
        {
            EditorGUI.LabelField(rect, "Default Disable Options");
        };

        m_List.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
        {
            SerializedProperty property = m_List.serializedProperty.GetArrayElementAtIndex(index);
            rect.height = EditorGUIUtility.singleLineHeight;
            EditorGUI.PropertyField(rect, property, new GUIContent("Index " + index.ToString()));
            //property.intValue = Mathf.Clamp(property.intValue, 0, drop.options.Count - 1);
            property.intValue = Mathf.Max(property.intValue, 0);
        };

        m_List.onAddCallback = (list) =>
        {
            list.serializedProperty.arraySize++;
            list.index = list.serializedProperty.arraySize - 1;
        };
    }

    public override void OnInspectorGUI()
    {
        EditorGUILayout.Space();
        EditorGUI.BeginChangeCheck();
        serializedObject.Update();
        m_List.DoLayoutList();
        serializedObject.ApplyModifiedProperties();
        if (EditorGUI.EndChangeCheck())
        {
            EditorUtility.SetDirty(target);
        }

        EditorGUILayout.Space();
        base.OnInspectorGUI();
    }
}
#endif
  • 如果你的Unity是5.x版本,那么UnityEditor.UI文件可能需要到Unity的安装目录去寻找手动添加进项目,拉入项目放在Editor文件夹内,导入设置只选Editor。
展开阅读全文

没有更多推荐了,返回首页