当前位置:   article > 正文

UGUI源码之Toggle组件_notifytoggleon

notifytoggleon

最近在像往常一样使用Toggle组件的时候,遇到一个问题:之前一直认为toggle组件是控制对象显示和隐藏从而实现单选的效果。然后那天一不小心将toggle组件控制的对象给手动隐藏掉了,然后发现改变toggle的IsOn属性无法达到单选的效果。接着就引发了思考,原来之前的理解是错误的。于是看了一下UGUI的源码是怎么实现的。

先来看下自己测试的结构:

然后说下其中的几个方法:

这个方法里面m_Group代表的就是我们测试的结构第二张图里面Toggle组件下绑定的Group,它是一个挂载了ToggleGroup组件的对象,大家应该知道Toggle组件的使用方法,就不多说了。这个方法里面主要是将当前的Toggle添加到ToggleGroup中来。代码的第二张图是ToggleGroup类中的方法。

这一段代码表示的就是:Toggle组件如何控制对象的淡入淡出。所以Toggle组件并不是将对象进行了显示隐藏。当m_isOn == true,CrossFadeAlpha()传入的第一个参数是1,这个1是做什么用的呢,继续往下看看

原来这个1这个位置的参数是决定透明度的。到这里我的疑惑就解决了,当然我没有继续深入研究这个方法,只是稍微了解了一下这个流程,以后再仔细研究。

再回到PlayEffect方法中来,上面提到了CrossFadeAlpha()方法,然后接下来说一下SetAlpha(),这个看上去也是像设置透明度,具体怎么操作的源码没有提供进一步的实现。不过知道的是这个代码是在Editor模式下就运行了 这也就是为什么我们项目结构的图片中我的Image没有显示出来的原因。

上面这一部分代码就是我们点击了IsOn以后的操作了,最终会执行到我们的PlayerEffect方法从而实现淡入淡出效果。这里有个M_Group.NotifyToggleOn(this)来说下这个方法的作用。

先来说下上面那个判断:m_Group.AnyTogglesOn()这个代表是否有开关打开了。m_Group.allowSwitchOff这个就是指我们的ToggleGroup组件下的勾选项

m_Group.allowSwitchOff默认为false,那么必须有且只有一个toggle的isOn为true。勾选中以后m_Group.allowSwitchOff = true,表示允许所有的Toggle组件isOn为false

来看看NotifyToggleOn做了什么操作吧:

其实就是把之前通过SetToggleGroup()方法添加进来的Toggle组件的ison设置为了false。

整理下完整的点击了IsOn的流程:

OnPointClick()就是被点击中触发的方法,关于点击的流程感兴趣的可以看看这个博客https://blog.csdn.net/wangjianxin97/article/details/96604461,然后贴上来整个Toggle的源码吧

  1. using System;
  2. using UnityEngine.Events;
  3. using UnityEngine.EventSystems;
  4. using UnityEngine.Serialization;
  5. namespace UnityEngine.UI
  6. {
  7. /// <summary>
  8. /// Simple toggle -- something that has an 'on' and 'off' states: checkbox, toggle button, radio button, etc.
  9. /// </summary>
  10. [AddComponentMenu("UI/Toggle", 31)]
  11. [RequireComponent(typeof(RectTransform))]
  12. public class Toggle : Selectable, IPointerClickHandler, ISubmitHandler, ICanvasElement
  13. {
  14. public enum ToggleTransition
  15. {
  16. None,
  17. Fade
  18. }
  19. [Serializable]
  20. public class ToggleEvent : UnityEvent<bool>
  21. {}
  22. /// <summary>
  23. /// Transition type.
  24. /// </summary>
  25. public ToggleTransition toggleTransition = ToggleTransition.Fade;
  26. /// <summary>
  27. /// Graphic the toggle should be working with.
  28. /// </summary>
  29. public Graphic graphic;
  30. // group that this toggle can belong to
  31. [SerializeField]
  32. private ToggleGroup m_Group;
  33. public ToggleGroup group
  34. {
  35. get { return m_Group; }
  36. set
  37. {
  38. m_Group = value;
  39. #if UNITY_EDITOR
  40. if (Application.isPlaying)
  41. #endif
  42. {
  43. SetToggleGroup(m_Group, true);
  44. PlayEffect(true);
  45. }
  46. }
  47. }
  48. /// <summary>
  49. /// Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers.
  50. /// </summary>
  51. public ToggleEvent onValueChanged = new ToggleEvent();
  52. // Whether the toggle is on
  53. [FormerlySerializedAs("m_IsActive")]
  54. [Tooltip("Is the toggle currently on or off?")]
  55. [SerializeField]
  56. private bool m_IsOn;
  57. protected Toggle()
  58. {}
  59. #if UNITY_EDITOR
  60. protected override void OnValidate()
  61. {
  62. base.OnValidate();
  63. var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this);
  64. if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying)
  65. CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
  66. }
  67. #endif // if UNITY_EDITOR
  68. public virtual void Rebuild(CanvasUpdate executing)
  69. {
  70. #if UNITY_EDITOR
  71. if (executing == CanvasUpdate.Prelayout)
  72. onValueChanged.Invoke(m_IsOn);
  73. #endif
  74. }
  75. public virtual void LayoutComplete()
  76. {}
  77. public virtual void GraphicUpdateComplete()
  78. {}
  79. protected override void OnEnable()
  80. {
  81. base.OnEnable();
  82. SetToggleGroup(m_Group, false);
  83. PlayEffect(true);
  84. }
  85. protected override void OnDisable()
  86. {
  87. SetToggleGroup(null, false);
  88. base.OnDisable();
  89. }
  90. protected override void OnDidApplyAnimationProperties()
  91. {
  92. // Check if isOn has been changed by the animation.
  93. // Unfortunately there is no way to check if we don�t have a graphic.
  94. if (graphic != null)
  95. {
  96. bool oldValue = !Mathf.Approximately(graphic.canvasRenderer.GetColor().a, 0);
  97. if (m_IsOn != oldValue)
  98. {
  99. m_IsOn = oldValue;
  100. Set(!oldValue);
  101. }
  102. }
  103. base.OnDidApplyAnimationProperties();
  104. }
  105. private void SetToggleGroup(ToggleGroup newGroup, bool setMemberValue)
  106. {
  107. ToggleGroup oldGroup = m_Group;
  108. // Sometimes IsActive returns false in OnDisable so don't check for it.
  109. // Rather remove the toggle too often than too little.
  110. if (m_Group != null)
  111. m_Group.UnregisterToggle(this);
  112. // At runtime the group variable should be set but not when calling this method from OnEnable or OnDisable.
  113. // That's why we use the setMemberValue parameter.
  114. if (setMemberValue)
  115. m_Group = newGroup;
  116. // Only register to the new group if this Toggle is active.
  117. if (newGroup != null && IsActive())
  118. newGroup.RegisterToggle(this);
  119. // If we are in a new group, and this toggle is on, notify group.
  120. // Note: Don't refer to m_Group here as it's not guaranteed to have been set.
  121. if (newGroup != null && newGroup != oldGroup && isOn && IsActive())
  122. newGroup.NotifyToggleOn(this);
  123. }
  124. /// <summary>
  125. /// Whether the toggle is currently active.
  126. /// </summary>
  127. public bool isOn
  128. {
  129. get { return m_IsOn; }
  130. set
  131. {
  132. Set(value);
  133. }
  134. }
  135. void Set(bool value)
  136. {
  137. Set(value, true);
  138. }
  139. void Set(bool value, bool sendCallback)
  140. {
  141. if (m_IsOn == value)
  142. return;
  143. // if we are in a group and set to true, do group logic
  144. m_IsOn = value;
  145. if (m_Group != null && IsActive())
  146. {
  147. Debug.Log("m_Group.AnyTogglesOn()"+m_Group.AnyTogglesOn());
  148. if (m_IsOn || (!m_Group.AnyTogglesOn() && !m_Group.allowSwitchOff))
  149. {
  150. Debug.Log("m_IsOn = " + m_IsOn);
  151. m_IsOn = true;
  152. m_Group.NotifyToggleOn(this);
  153. }
  154. }
  155. // Always send event when toggle is clicked, even if value didn't change
  156. // due to already active toggle in a toggle group being clicked.
  157. // Controls like Dropdown rely on this.
  158. // It's up to the user to ignore a selection being set to the same value it already was, if desired.
  159. PlayEffect(toggleTransition == ToggleTransition.None);
  160. if (sendCallback)
  161. onValueChanged.Invoke(m_IsOn);
  162. }
  163. /// <summary>
  164. /// Play the appropriate effect.
  165. /// </summary>
  166. private void PlayEffect(bool instant)
  167. {
  168. Debug.Log("m_IsOn" + m_IsOn);
  169. if (graphic == null)
  170. return;
  171. #if UNITY_EDITOR
  172. if (!Application.isPlaying)
  173. {
  174. graphic.canvasRenderer.SetAlpha(m_IsOn ? 1f : 0f);
  175. }
  176. else
  177. #endif
  178. {
  179. graphic.CrossFadeAlpha(m_IsOn ? 1f : 0f, instant ? 0f : 0.1f, true);
  180. }
  181. }
  182. /// <summary>
  183. /// Assume the correct visual state.
  184. /// </summary>
  185. protected override void Start()
  186. {
  187. PlayEffect(true);
  188. }
  189. private void InternalToggle()
  190. {
  191. if (!IsActive() || !IsInteractable())
  192. return;
  193. isOn = !isOn;
  194. }
  195. /// <summary>
  196. /// React to clicks.
  197. /// </summary>
  198. public virtual void OnPointerClick(PointerEventData eventData)
  199. {
  200. if (eventData.button != PointerEventData.InputButton.Left)
  201. return;
  202. InternalToggle();
  203. }
  204. public virtual void OnSubmit(BaseEventData eventData)
  205. {
  206. InternalToggle();
  207. }
  208. }
  209. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/118362
推荐阅读
相关标签
  

闽ICP备14008679号