自动布局和固定布局交叉使用
预留布局位置——GetRect|GetControlRect
- 这也是我经常会遇到的问题,我想把自动布局和固定布局交替使用,所以需要获取
rect 数据 - 需要注意的是,
GetRect 函数本身就是预留空间,无论你是否在该空间绘制东西,这片空间都会占用
Rect rect = GUILayoutUtility.GetRect(10, EditorGUIUtility.singleLineHeight*5);
GUILayout.Button("我是下面的控件", GUILayout.Width(100), GUILayout.Height(100));
- 可以看到,这片空间是空着的,接下来绘制的
button 按钮也是在其后的 GetControlRect 和他的作用差不多
var rect = EditorGUILayout.GetControlRect(GUILayout.height(50));
GUILayout.Button("我是下一个控件");
通过反编译来取证
- 我一开始怀疑
GetControlRect 和GetRect 函数内部调用了相同的函数 - 所以我就通过反编译(使用DnSpy)
UnityEditor.dll 发现果然如此 - 结果如下
- 可以看到
GetControlRect 函数内部还是调用了GUILayoutUtility.GetRect GUILayout.GetRect() 函数内部又调用了自身的DoGetRect - 可以看到
DoGetRect 本身是一个私有方法,没有暴露出来。所以我们没法使用
获取上一个控件的rect位置——GetLastRect
GUILayout.Button("My button");
if (Event.current.type == EventType.Repaint &&
GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
{
GUILayout.Label("Mouse over!");
}
else
{
GUILayout.Label("Mouse somewhere else");
}
- 可以看到,当鼠标移动到
MyButton 按钮区域的时候,下方的字体就会显示为MouseOver
使用案例
两个接口在绘制背景时候的使用
- 因为绘制背景需要重叠绘制,即一个控件绘制背景,另一个要绘制在它上面,所以我们无可避免的要使用上面两个接口
- 有时候需要在自动布局的时候,绘制背景,就可以使用上面两个接口
- 第一种方法,首先使用
GetLastRect 获得上个自动布局控件的位置,然后计算下一个控件的位置,用GUI 绘制的控件,不会占据GUILayout 绘制的位置,所以可以重叠,实现背景
var lastRect = GUILayoutUtility.GetLastRect();
var newLastRect = new Vector2(lastRect.x, lastRect.y + lastRect.height+2);
EditorGUI.DrawRect(new Rect(newLastRect, new Vector2(lastRect.width, 30)), Color.green);
GUILayout.Button("我是下面的控件", new GUIStyle("button") { margin = new RectOffset(0, 0, 0, 0) }, GUILayout.Width(100), GUILayout.Height(30));
- 可以看到我绘制的绿色背景
- 第二种方法,其实和第一种差不多,只不过他是用
GetRect 函数来计算获得下一个控件的位置,相当于把我GetLastRect+height 这一步省略了,代码如下
Rect rect = GUILayoutUtility.GetRect(0, 0).ResizeHeight(height);
GUI.Box(rect, "",EditorStyles.textArea);
- 如果把代码改成
GUILayoutUtility.GetRect(0,height) 就会变成下面情况,高度占用了空间
在绘制同一行的时候使用
GUILayout.BeginHorizontal();
GUILayout.Label("我是第一个位置",GUILayout.ExpandWidth(false));
var rect = EditorGUILayout.GetControlRect();
GUILayout.Button("我是第三个");
GUI.Button(rect, new GUIContent("我是下一个"));
GUILayout.EndHorizontal();
- 可以看到,即使在同一行中,使用这个函数同样有效
- 另外我想说
- 如果你不指明控件的宽度和高度,他会自动使用
EditorGUIUtility.singleLineHeight ,这个高度就是18,而宽度则会默认取尽可能扩展的宽度
GetControlRect()== GUILayoutUtility.GetRect(0,18);
|