参考 https://docs.unity3d.com/Manual/UIE-uxml-examples.html
实现纯图片按钮
.image-button {
background-color: rgba(0, 0, 0, 0);
-unity-background-image-tint-color: rgb(200, 200, 200);
border-left-width: 0;
border-right-width: 0;
border-top-width: 0;
border-bottom-width: 0;
}
.image-button:hover:enabled {
-unity-background-image-tint-color: rgb(255, 255, 255);
}
.image-button:hover:active:enabled {
-unity-background-image-tint-color: #888888;
}
列表设置元素间距
- 设置 ListView 的 fixItemHeight=50
- 创建列表元素时,列表元素会自动设置高为50,添加一个子元素,设置height=40,则剩下的10做为间距
- 接下来就是把鼠标悬停、选中效果从列表元素转移到子元素上
- 创建列表元素时,给子元素添加 item-back 样式,或直接在UIBuilder中添加
- 在界面中引用如下样式文件,就2个作用,清除原本的列表元素样式,设置子元素样式
.unity-list-view__item { background-color: rgba(0, 0, 0, 0); } .unity-list-view__item:hover { background-color: rgba(0, 0, 0, 0); } .unity-list-view__item:checked { background-color: rgba(0, 0, 0, 0); } .unity-list-view__item:checked .item-back { border-left-color: rgba(12, 122, 237, 255); border-right-color: rgba(12, 122, 237, 255); border-top-color: rgba(12, 122, 237, 255); border-bottom-color: rgba(12, 122, 237, 255); } .unity-list-view__item:hover .item-back { border-left-color: rgba(85, 162, 242, 255); border-right-color: rgba(85, 162, 242, 255); border-top-color: rgba(85, 162, 242, 255); border-bottom-color: rgba(85, 162, 242, 255); }
Editor模式下自定义Tooltip
主要有2个难点
- 让窗口适配文本大小
获取文本大小有2种方案- 监听Label的 GeometryChangedEvent 事件,通过 resolvedStyle 获取大小
Rect(element.resolvedStyle.left, element.resolvedStyle.top, element.resolvedStyle.width, element.resolvedStyle.height) - 使用 TextElement.MeasureTextSize 直接计算文本占用的大小
- 监听Label的 GeometryChangedEvent 事件,通过 resolvedStyle 获取大小
- 让窗口自动显示在控件的上下左右合适的地方
当前也有2种方案- 使用unity提供的自动对齐
有2个api可以实现,EditorWindow.ShowAsDropDown 和 PopupWindow.Show
这2个api都可以显示弹窗,区别就在于 PopupWindow 可以在窗口显示后更改窗口大小,而 EditorWindow.ShowAsDropDown 则不行
而上面获取文本大小又需要窗口显示后才能获取,因此最终方案是使用 PopupWindow.Show
PopupWindow 会在 OnGUI 函数中调用 FitWindowToContent 实现实时更新窗口大小,最终是调用 ContainerWindow.GetDropDownRect ,这是内部函数 - 自己计算位置
自己计算位置的最大问题是没找到获取所有屏幕的屏幕范围的方法
操作系统是把所有显示器的显示范围都统一到一个虚拟坐标系中,只要能获取所有屏幕的显示范围,就可以计算出提示应该摆在哪里
unity中只提供了 Display.displays 获取显示器大小,但缺少获取偏移的api
最终实现是使用 1.1 + 2.1 来解决,也就是 PopupWindow.Show + 监听 GeometryChangedEvent
- 使用unity提供的自动对齐
public class CustomTooltip : PopupWindowContent
{
private static CustomTooltip instance;
private string tip;
private Vector2 tipSize = new Vector2(100, 100); // 给一个初始值
private Label tooltipLabel;
// targetBounds 是需要提示的控件的边框
public static void ShowTooltip(string text, Rect targetBounds)
{
HideTooltip();
instance = new CustomTooltip(text);
UnityEditor.PopupWindow.Show(targetBounds, instance);
}
public static void HideTooltip()
{
if (instance != null && instance.editorWindow != null)
{
try
{
instance.editorWindow.Close();
} catch (Exception e) {
}
}
instance = null;
}
public CustomTooltip(string tip)
{
this.tip = tip;
}
public override Vector2 GetWindowSize()
{
return tipSize;
}
public override void OnOpen()
{
InitializeUI();
tooltipLabel.text = tip;
tooltipLabel.RegisterCallback<GeometryChangedEvent>(OnFirstInit);
}
private void InitializeUI()
{
var root = editorWindow.rootVisualElement;
// root 的 flexDirection = FlexDirection.Column
// 必须再添加一个 flexDirection = FlexDirection.Row 的元素,不然lable大小计算有问题
VisualElement tooltipContainer = new VisualElement();
tooltipContainer.style.flexDirection = FlexDirection.Row;
root.Add(tooltipContainer);
tooltipLabel = new Label();
tooltipLabel.style.color = new Color(0.733f,0.733f,0.733f,1);
tooltipLabel.style.backgroundColor = new Color(0.18f,0.18f,0.196f,1);
tooltipLabel.style.fontSize = 12;
tooltipLabel.style.position = Position.Absolute;
tooltipLabel.style.paddingLeft = tooltipLabel.style.paddingRight = 8;
tooltipLabel.style.paddingTop = tooltipLabel.style.paddingBottom = 5;
tooltipContainer.Add(tooltipLabel);
}
// 用文本大小做为窗口大小
private void OnFirstInit(GeometryChangedEvent evt)
{
tooltipLabel.UnregisterCallback<GeometryChangedEvent>(OnFirstInit);
tipSize = new Vector2(instance.tooltipLabel.resolvedStyle.width, instance.tooltipLabel.resolvedStyle.height);
}
public override void OnClose()
{
instance = null;
}
public override void OnGUI(Rect rect)
{
}
}
public static class CustomTooltipExtensions
{
public static void AddCustomTooltip(this VisualElement element, string tooltipText)
{
element.RegisterCallback<MouseEnterEvent>(evt =>
{
Rect rc = element.worldBound;
// 使用 PopupWindow 会自动转换,就不需要在这里转换了
// rc.position = rc.position + EditorWindow.mouseOverWindow.position.position;
CustomTooltip.ShowTooltip(tooltipText, rc);
});
element.RegisterCallback<MouseLeaveEvent>(evt =>
{
CustomTooltip.HideTooltip();
});
}
}