了解

  1. 单行高度:EditorGUIUtility.singleLineHeight
  2. 获取 PropertyField 控件所需的高度:EditorGUI.GetPropertyHeight
  3. 属性是否在Inspector窗口展开:SerializedProperty.isExpanded
  4. 可重新排序列表类:ReorderableList
  5. 绘制纯色矩形:EditorGUI.DrawRect

示例

使用版本:2021.3.6f1c1
此版本的Unity已经实现数组元素添加,移除,移动功能。

自定义类

[System.Serializable]
public class Test 
{
    public string name;
    public int age;
}

数据类

定义一个数组,数组元素为自定义类

using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class TestSO : ScriptableObject
{
    public List<Test> testList;
}

数据类文件默认显示如下

在这里插入图片描述

修改数据类显示

数据元素内容显示为一行

注意:不能使用自动布局api

using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(Test))]
public class TestDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        var spName = property.FindPropertyRelative("name");
        var spAge = property.FindPropertyRelative("age");

        var rect1 = position;
        var rect2 = position;

        var indentlevel = EditorGUI.indentLevel;
        var lableWidth = EditorGUIUtility.labelWidth;
        EditorGUI.indentLevel = 2;
        EditorGUIUtility.labelWidth = 60;

        rect1.width = position.width / 2;
        rect1.height = EditorGUIUtility.singleLineHeight;

        rect2.width = position.width / 2;
        rect2.height = EditorGUIUtility.singleLineHeight;

        rect2.x = position.width / 2+40;
        rect2.y = rect1.y;

        EditorGUI.PropertyField(rect1, spName, new GUIContent("名字"));
        EditorGUI.PropertyField(rect2, spAge, new GUIContent("年龄"));

        EditorGUI.indentLevel = indentlevel;
        EditorGUIUtility.labelWidth = lableWidth;

        //EditorGUI.DrawRect(rect1, Color.green);
        //EditorGUI.DrawRect(rect2, Color.gray);
    }

	//获取属性高度
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return base.GetPropertyHeight(property, label);
    }
}

修改后显示效果如下图所示
在这里插入图片描述

TestList修改为指定名称;Element修改为指定名称

using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(TestSO))]
public class TestSOEditor : Editor
{
    SerializedProperty sPTestList;
    ReorderableList arrayList;

    private void OnEnable()
    {
        sPTestList = serializedObject.FindProperty("testList");

        if (arrayList == null)
        {
            arrayList = new ReorderableList(serializedObject, sPTestList, true, true, true, true);    
            //绘制Header
            arrayList.drawHeaderCallback += DrawHeader;
            //绘制数组元素
            arrayList.drawElementCallback += DrawElement;
            //获取数组的高度
            arrayList.elementHeightCallback += DrawElementHeight;
        }
    }

    void DrawHeader(Rect rect)
    {
        EditorGUI.LabelField(rect, "测试列表");
    }

    void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
    {
        var element = sPTestList.GetArrayElementAtIndex(index);
        var arrowRect = rect;

        int indentLevel = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 1;
        arrowRect.height = EditorGUIUtility.singleLineHeight;
        element.isExpanded = EditorGUI.Foldout(arrowRect, element.isExpanded, new GUIContent("元素" + index));
        EditorGUI.indentLevel = indentLevel;

        //EditorGUI.DrawRect(rect, Color.red);
        //EditorGUI.DrawRect(arrowRect, Color.blue);

        if (element.isExpanded)
        {
            rect.y += arrowRect.height;
            EditorGUI.PropertyField(rect, element);
        }
    }

    float DrawElementHeight(int index)
    {
        var element = sPTestList.GetArrayElementAtIndex(index);
        var height = EditorGUIUtility.singleLineHeight;//折叠箭头的高度   
        if (element.isExpanded)//如果元素展开 获取展开内容的高度和箭头的高度之和
            height += EditorGUI.GetPropertyHeight(element);
        return height;
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        arrayList.DoLayoutList();
        serializedObject.ApplyModifiedProperties();
    }
}

修改后如下图所示
在这里插入图片描述

示例二

高度计算放在PropertyDrawer的OnGUI中

自定义类

显示折叠箭头,数据元素内容显示为一行,Element修改为指定名称

using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(Test))]
public class TestDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        var spName = property.FindPropertyRelative("name");
        var spAge = property.FindPropertyRelative("age");

        var rect0 = position;
        rect0.height = EditorGUIUtility.singleLineHeight;

        var indentlevel = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 1;
      
        property.isExpanded = EditorGUI.Foldout(rect0, property.isExpanded, label);
      
        EditorGUI.indentLevel = indentlevel;

        if (property.isExpanded)
        {
            var rect1 = position;
            var rect2 = position;

            indentlevel = EditorGUI.indentLevel;
            var lableWidth = EditorGUIUtility.labelWidth;
            EditorGUI.indentLevel = 2;
            EditorGUIUtility.labelWidth = 60;

            rect1.width = position.width / 2;
            rect1.height = EditorGUIUtility.singleLineHeight;
            rect1.y += EditorGUIUtility.singleLineHeight;

            rect2.width = position.width / 2;
            rect2.height = EditorGUIUtility.singleLineHeight;

            rect2.x = position.width / 2 + 40;
            rect2.y = rect1.y;

            EditorGUI.PropertyField(rect1, spName, new GUIContent("名字"));
            EditorGUI.PropertyField(rect2, spAge, new GUIContent("年龄"));

            EditorGUI.indentLevel = indentlevel;
            EditorGUIUtility.labelWidth = lableWidth;
            //EditorGUI.DrawRect(rect1, Color.green);
            //EditorGUI.DrawRect(rect2, Color.gray);
        }
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        if (property.isExpanded)
            return EditorGUIUtility.singleLineHeight * 2;
        else
            return EditorGUIUtility.singleLineHeight;
    }
}

数据类

TestList修改为指定名称

using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(TestSO))]
public class TestSOEditor : Editor
{
    SerializedProperty sPTestList;
    ReorderableList arrayList;

    private void OnEnable()
    {
        sPTestList = serializedObject.FindProperty("testList");
        if (arrayList == null)
        {
            arrayList = new ReorderableList(serializedObject, sPTestList, true, true, true, true);
            //绘制Header
            arrayList.drawHeaderCallback += DrawHeader;
            //绘制数组元素
            arrayList.drawElementCallback += DrawElement;
            //绘制元素高度
            arrayList.elementHeightCallback += DrawHeight;

            void DrawHeader(Rect rect)
            {
                EditorGUI.LabelField(rect, "测试列表");
            }

            void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
            {
            	//参数会传递给PropertyDrawer的OnGUI 
                EditorGUI.PropertyField(rect, sPTestList.GetArrayElementAtIndex(index), new GUIContent("元素 " + index));
            }

            float DrawHeight(int index)
            {
                return EditorGUI.GetPropertyHeight(sPTestList.GetArrayElementAtIndex(index));
            }
        }
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        arrayList.DoLayoutList();
        serializedObject.ApplyModifiedProperties();
    }
}

参考

看完后理解列表的高度如何计算

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部