提供了xericimage,这个组件可以帮助我们追踪toggle的checkmark事件,因为toggle的事件都没有提供重写,目前的c#版本也不支持钩子,所以这样是比较优的方案。
This commit is contained in:
@@ -18,9 +18,11 @@ namespace XericUIEditor.OverrideUI
|
||||
|
||||
SerializedProperty m_TextProperty;
|
||||
SerializedProperty m_EnableTextColorTransitionProperty;
|
||||
SerializedProperty m_isonStatusColor;
|
||||
SerializedProperty m_TextTransitionColorModeProperty;
|
||||
SerializedProperty m_enableTextContextTransitionProperty;
|
||||
SerializedProperty m_textTransitionContextModeProperty;
|
||||
SerializedProperty m_isonStatusTextContext;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
@@ -34,9 +36,11 @@ namespace XericUIEditor.OverrideUI
|
||||
|
||||
m_TextProperty = serializedObject.FindProperty("m_text");
|
||||
m_EnableTextColorTransitionProperty = serializedObject.FindProperty("m_enableTextColorTransition");
|
||||
m_isonStatusColor = serializedObject.FindProperty("m_isonStatusColor");
|
||||
m_TextTransitionColorModeProperty = serializedObject.FindProperty("m_textTransitionColorMode");
|
||||
m_enableTextContextTransitionProperty = serializedObject.FindProperty("m_enableTextContextTransition");
|
||||
m_textTransitionContextModeProperty = serializedObject.FindProperty("m_textTransitionContextMode");
|
||||
m_isonStatusTextContext = serializedObject.FindProperty("m_isonStatusTextContext");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
@@ -76,6 +80,7 @@ namespace XericUIEditor.OverrideUI
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.PropertyField(m_TextTransitionColorModeProperty);
|
||||
EditorGUILayout.PropertyField(m_isonStatusColor);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
EditorGUILayout.PropertyField(m_enableTextContextTransitionProperty);
|
||||
@@ -83,6 +88,7 @@ namespace XericUIEditor.OverrideUI
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.PropertyField(m_textTransitionContextModeProperty);
|
||||
EditorGUILayout.PropertyField(m_isonStatusTextContext);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace XericUI.OverrideLayout
|
||||
/// <summary>
|
||||
/// 对象数据
|
||||
/// </summary>
|
||||
[SerializeField] private readonly List<ScrollItemData> _childrenDatas = ListPool<ScrollItemData>.Get();
|
||||
[SerializeField] private readonly List<ScrollItemData> _childrenDatas = new List<ScrollItemData>();
|
||||
|
||||
public Vector2 ContextSize
|
||||
{
|
||||
@@ -83,6 +83,7 @@ namespace XericUI.OverrideLayout
|
||||
|
||||
private Queue<RectTransform> _activeQueue = new Queue<RectTransform>();
|
||||
|
||||
private bool layoutHasRebuildAtThisFrame;
|
||||
private bool layoutDirty;
|
||||
private bool indexMapDirty;
|
||||
|
||||
@@ -97,20 +98,21 @@ namespace XericUI.OverrideLayout
|
||||
private bool _uiVisibal;
|
||||
|
||||
protected GameObject item;
|
||||
|
||||
public RectTransform itemRectTransform => item ? item.RectTransform() : null;
|
||||
public IUIVesselVisibalControl ItemUIVesselVisibalControlComponent => item ? itemRectTransform.GetComponent<IUIVesselVisibalControl>() : null;
|
||||
public bool GetUIVisibal => _uiVisibal;
|
||||
|
||||
public virtual void UnderVisibal()
|
||||
{
|
||||
item = parentScrollRect.childrenPool.Get();
|
||||
var rectTransform = item.RectTransform();
|
||||
parentScrollRect.UpdateChildPivot(layout, item.RectTransform());
|
||||
rectTransform.anchoredPosition = layout.position;
|
||||
itemRectTransform.anchoredPosition = layout.position;
|
||||
}
|
||||
|
||||
public virtual void OutOfVisibal()
|
||||
{
|
||||
parentScrollRect.childrenPool.DirectlyRelease(item);
|
||||
item = null;
|
||||
}
|
||||
|
||||
public void UpdateLayout(GridLayoutCalculator.LayoutItem layoutData)
|
||||
@@ -211,18 +213,22 @@ namespace XericUI.OverrideLayout
|
||||
{
|
||||
// 只有距离大于这个才会触发更新
|
||||
_lastContextAnchoredPosition = position;
|
||||
UpdateAAMVSVisibleStatus(position);
|
||||
UpdateAAMVSVisibleStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LateUpdate()
|
||||
{
|
||||
layoutHasRebuildAtThisFrame = false;
|
||||
base.LateUpdate();
|
||||
// 布局刷新
|
||||
if (layoutDirty)
|
||||
{
|
||||
layoutDirty = false;
|
||||
// 常规的刷新依赖视图的更新,如果这一帧只增删了对象,但是视图没有移动,那么这里就会执行更新
|
||||
if (layoutHasRebuildAtThisFrame)
|
||||
UpdateAAMVSVisibleStatus();
|
||||
RefreshLayout();
|
||||
}
|
||||
// 全部索引刷新
|
||||
@@ -239,8 +245,9 @@ namespace XericUI.OverrideLayout
|
||||
/// <summary>
|
||||
/// 自动剔除更新标记
|
||||
/// </summary>
|
||||
protected void UpdateAAMVSVisibleStatus(Vector2 position)
|
||||
protected void UpdateAAMVSVisibleStatus()
|
||||
{
|
||||
layoutHasRebuildAtThisFrame = true;
|
||||
// 将视口尺寸转换到content本地空间
|
||||
// 手动计算视口在content空间的矩形
|
||||
viewport.GetWorldCorners(viewportVertex);
|
||||
@@ -261,57 +268,68 @@ namespace XericUI.OverrideLayout
|
||||
// horizontal ? horizontalScrollbar?.value ?? 0 : 0,
|
||||
// vertical ? 1 - (verticalScrollbar?.value ?? 1) : 0);
|
||||
|
||||
// ReSharper disable once PossibleInvalidCastExceptionInForeachLoop
|
||||
foreach (RectTransform child in content.GetChildren())
|
||||
foreach (var childData in _childrenDatas)
|
||||
{
|
||||
var visControl = child.GetComponent<IUIVesselVisibalControl>();
|
||||
var isVisControlValid = visControl != null;
|
||||
var childRectTransform = childData.itemRectTransform;
|
||||
if (childRectTransform)
|
||||
{
|
||||
var visControl = childData.ItemUIVesselVisibalControlComponent;
|
||||
var isVisControlValid = visControl != null;
|
||||
|
||||
// 直接使用anchoredPosition进行边界检测
|
||||
var childPos = childRectTransform.anchoredPosition;
|
||||
var isVisible = CheckIsVisibal(childPos);
|
||||
var nowActive = childRectTransform.GetActivity();
|
||||
|
||||
var rectTransform = child.RectTransform();
|
||||
// 直接使用anchoredPosition进行边界检测
|
||||
var childPos = rectTransform.anchoredPosition;
|
||||
var isVisible =
|
||||
childPos.x >= visibleMin.x &&
|
||||
childPos.x <= visibleMax.x &&
|
||||
childPos.y >= visibleMin.y &&
|
||||
childPos.y <= visibleMax.y;
|
||||
// 以接口为准
|
||||
if (isVisControlValid)
|
||||
nowActive = visControl.GetUIVisibal;
|
||||
|
||||
var nowActive = child.GetActivity();
|
||||
// 现在的状态与实际一致,跳过
|
||||
if (isVisible == nowActive)
|
||||
continue;
|
||||
|
||||
// 以接口为准
|
||||
if (isVisControlValid)
|
||||
nowActive = visControl.GetUIVisibal;
|
||||
|
||||
// 现在的状态与实际一致,跳过
|
||||
if (isVisible == nowActive)
|
||||
continue;
|
||||
|
||||
// 向成员发送状态(如果成员没有实现接口,就直接通过可见性控制)
|
||||
if (isVisControlValid)
|
||||
visControl.CallVisibal(isVisible);
|
||||
// 向成员发送状态(如果成员没有实现接口,就直接通过可见性控制)
|
||||
if (isVisControlValid)
|
||||
visControl.CallVisibal(isVisible);
|
||||
else
|
||||
childRectTransform.gameObject.SetActive(isVisible);
|
||||
}
|
||||
else
|
||||
child.gameObject.SetActive(isVisible);
|
||||
{
|
||||
var isVisible = CheckIsVisibal(childData.layout.position);
|
||||
if (isVisible)
|
||||
{
|
||||
childData.UnderVisibal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckIsVisibal(Vector2 pos)
|
||||
{
|
||||
return
|
||||
pos.x >= visibleMin.x &&
|
||||
pos.x <= visibleMax.x &&
|
||||
pos.y >= visibleMin.y &&
|
||||
pos.y <= visibleMax.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 数据管理
|
||||
|
||||
public T GetScrollItemData<T>()
|
||||
where T : ScrollItemData, new()
|
||||
{
|
||||
var result = new T
|
||||
{
|
||||
parentScrollRect = this
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个子项(自行重写这个子项类型数据结构,基于其中的生命周期函数完成内容的更新)
|
||||
/// </summary>
|
||||
/// <param name="Data"></param>
|
||||
public void AddChildData(ScrollItemData Data)
|
||||
{
|
||||
layoutDirty = true;
|
||||
Data.index = _childrenDatas.Count;
|
||||
Data.parentScrollRect = this;
|
||||
_childrenDatas.Add(Data);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
using XericUI.Helper;
|
||||
|
||||
namespace XericUI.OverrideUI
|
||||
{
|
||||
/// <summary>
|
||||
/// 图像组件
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 这个组件主要为了提供graphic层的事件,用于应对部分无法重写的ui组件事件
|
||||
/// </remarks>
|
||||
public class XericImage : Image
|
||||
{
|
||||
/// <summary>
|
||||
/// 针对toggle的回报(ison)
|
||||
/// </summary>
|
||||
internal Action<bool> OnToggleCrossFadeCall;
|
||||
public override void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha, bool useRGB)
|
||||
{
|
||||
base.CrossFadeColor(targetColor, duration, ignoreTimeScale, useAlpha, useRGB);
|
||||
OnToggleCrossFadeCall?.Invoke(targetColor.a > 0);
|
||||
}
|
||||
|
||||
#region 组件替换
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.MenuItem("CONTEXT/Image/Replace To XericImage", true)]
|
||||
private static bool ValidateReplaceToXeric(UnityEditor.MenuCommand command)
|
||||
=> command.context is Image and not XericImage;
|
||||
|
||||
[UnityEditor.MenuItem("CONTEXT/Image/Replace To XericImage", false, 10)]
|
||||
private static void ReplaceToXeric(UnityEditor.MenuCommand command)
|
||||
=> command.ReplaceCommandContext<Image, XericImage, Sprite>(
|
||||
o =>
|
||||
o.sprite,
|
||||
(t, d) =>
|
||||
{
|
||||
t.sprite = d;
|
||||
});
|
||||
|
||||
[UnityEditor.MenuItem("CONTEXT/Image/Replace To Image", true)]
|
||||
private static bool ValidateReplaceToUnity(UnityEditor.MenuCommand command)
|
||||
=> command.context is XericImage;
|
||||
|
||||
[UnityEditor.MenuItem("CONTEXT/Image/Replace To Image", false, 10)]
|
||||
private static void ReplaceToUnity(UnityEditor.MenuCommand command)
|
||||
=> command.ReplaceCommandContext<XericImage, Image, Sprite>(
|
||||
o =>
|
||||
o.sprite,
|
||||
(t, d) =>
|
||||
{
|
||||
t.sprite = d;
|
||||
});
|
||||
#endif
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52aeb4e8bd3a4b6c9513b8ad21b41558
|
||||
timeCreated: 1776850195
|
||||
@@ -6,6 +6,7 @@ using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
using XericUI.Helper;
|
||||
using XericUI.OverrideUI;
|
||||
|
||||
namespace XericUI
|
||||
{
|
||||
@@ -46,6 +47,7 @@ namespace XericUI
|
||||
|
||||
public bool m_enableTextColorTransition = true;
|
||||
public ColorBlock m_textTransitionColorMode = ColorBlock.defaultColorBlock;
|
||||
public Color m_isonStatusColor = Color.white;
|
||||
public bool m_enableTextContextTransition = false;
|
||||
public AnimationTriggers m_textTransitionContextMode = new AnimationTriggers()
|
||||
{
|
||||
@@ -55,6 +57,9 @@ namespace XericUI
|
||||
selectedTrigger = "toggle_selected",
|
||||
disabledTrigger = "toggle_disabled",
|
||||
};
|
||||
|
||||
public string m_isonStatusTextContext = "toggle_ison";
|
||||
|
||||
|
||||
public bool EnableTextColorTransition
|
||||
{
|
||||
@@ -67,7 +72,39 @@ namespace XericUI
|
||||
get => m_textTransitionColorMode;
|
||||
set => m_textTransitionColorMode = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private XericImage m_ximage;
|
||||
|
||||
protected XericImage ximage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_ximage)
|
||||
return m_ximage;
|
||||
#if UNITY_EDITOR
|
||||
if (!graphic)
|
||||
return null;
|
||||
#endif
|
||||
m_ximage = graphic.GetComponent<XericImage>();
|
||||
if (m_ximage)
|
||||
return m_ximage;
|
||||
Debug.Log("注意替换toggle的checkmark为XericImage以支持完整的功能");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool bindXImage;
|
||||
|
||||
protected override void InstantClearState()
|
||||
{
|
||||
base.InstantClearState();
|
||||
|
||||
if (m_enableTextColorTransition)
|
||||
TextColor = colors.normalColor;
|
||||
if (m_enableTextContextTransition)
|
||||
TextContent = m_textTransitionContextMode.normalTrigger;
|
||||
}
|
||||
protected override void DoStateTransition(SelectionState state, bool instant)
|
||||
{
|
||||
if (!gameObject.activeInHierarchy)
|
||||
@@ -117,8 +154,8 @@ namespace XericUI
|
||||
transitionName = m_textTransitionContextMode.disabledTrigger;
|
||||
break;
|
||||
default:
|
||||
tintColor = Color.black;
|
||||
textColor = Color.white;
|
||||
tintColor = colors.normalColor;
|
||||
textColor = m_textTransitionColorMode.normalColor;
|
||||
transitionSprite = null;
|
||||
triggerName = string.Empty;
|
||||
transitionName = m_textTransitionContextMode.normalTrigger;
|
||||
@@ -138,13 +175,25 @@ namespace XericUI
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bindXImage && ximage != null)
|
||||
{
|
||||
bindXImage = true;
|
||||
ximage.OnToggleCrossFadeCall = b =>
|
||||
{
|
||||
if (m_enableTextColorTransition)
|
||||
TextColor = b ? m_textTransitionColorMode.pressedColor : m_textTransitionColorMode.normalColor;
|
||||
if (m_enableTextContextTransition)
|
||||
TextContent = b ? m_textTransitionContextMode.pressedTrigger : m_textTransitionContextMode.normalTrigger;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
if (m_enableTextColorTransition)
|
||||
TextColor = isOn ? m_textTransitionColorMode.selectedColor : textColor;
|
||||
TextColor = isOn ? m_isonStatusColor : textColor;
|
||||
if (m_enableTextContextTransition)
|
||||
TextContent = transitionName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void StartColorTween(Color targetColor, bool instant)
|
||||
{
|
||||
if (targetGraphic == null)
|
||||
@@ -184,8 +233,9 @@ namespace XericUI
|
||||
=> command.context is Toggle and not XericToggle;
|
||||
|
||||
[UnityEditor.MenuItem("CONTEXT/Toggle/Replace To XericToggle", false, 10)]
|
||||
private static void ReplaceToXeric(UnityEditor.MenuCommand command)
|
||||
=> command.ReplaceCommandContext<Toggle, XericToggle,
|
||||
private static void ReplaceToXeric(UnityEditor.MenuCommand command)
|
||||
{
|
||||
command.ReplaceCommandContext<Toggle, XericToggle,
|
||||
(Graphic graphic, ToggleGroup group, ToggleEvent onValueChanged)>(
|
||||
o =>
|
||||
(o.graphic, o.group, o.onValueChanged),
|
||||
@@ -195,6 +245,8 @@ namespace XericUI
|
||||
t.group = d.group;
|
||||
t.onValueChanged = d.onValueChanged;
|
||||
});
|
||||
Debug.Log("请手动替换toggle下的Checkmark Image组件为XericImage,否则Toggle工作时取消选择的状态会保持为ison状态。");
|
||||
}
|
||||
|
||||
[UnityEditor.MenuItem("CONTEXT/Toggle/Replace To Toggle", true)]
|
||||
private static bool ValidateReplaceToUnity(UnityEditor.MenuCommand command)
|
||||
@@ -214,5 +266,6 @@ namespace XericUI
|
||||
});
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user