赞
踩
最近在像往常一样使用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的源码吧
- using System;
- using UnityEngine.Events;
- using UnityEngine.EventSystems;
- using UnityEngine.Serialization;
-
- namespace UnityEngine.UI
- {
- /// <summary>
- /// Simple toggle -- something that has an 'on' and 'off' states: checkbox, toggle button, radio button, etc.
- /// </summary>
- [AddComponentMenu("UI/Toggle", 31)]
- [RequireComponent(typeof(RectTransform))]
- public class Toggle : Selectable, IPointerClickHandler, ISubmitHandler, ICanvasElement
- {
- public enum ToggleTransition
- {
- None,
- Fade
- }
-
- [Serializable]
- public class ToggleEvent : UnityEvent<bool>
- {}
-
- /// <summary>
- /// Transition type.
- /// </summary>
- public ToggleTransition toggleTransition = ToggleTransition.Fade;
-
- /// <summary>
- /// Graphic the toggle should be working with.
- /// </summary>
- public Graphic graphic;
-
- // group that this toggle can belong to
- [SerializeField]
- private ToggleGroup m_Group;
-
- public ToggleGroup group
- {
- get { return m_Group; }
- set
- {
- m_Group = value;
- #if UNITY_EDITOR
- if (Application.isPlaying)
- #endif
- {
- SetToggleGroup(m_Group, true);
- PlayEffect(true);
- }
- }
- }
-
- /// <summary>
- /// Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers.
- /// </summary>
- public ToggleEvent onValueChanged = new ToggleEvent();
-
- // Whether the toggle is on
- [FormerlySerializedAs("m_IsActive")]
- [Tooltip("Is the toggle currently on or off?")]
- [SerializeField]
- private bool m_IsOn;
-
- protected Toggle()
- {}
-
- #if UNITY_EDITOR
- protected override void OnValidate()
- {
- base.OnValidate();
-
- var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this);
- if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying)
- CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
- }
-
- #endif // if UNITY_EDITOR
-
- public virtual void Rebuild(CanvasUpdate executing)
- {
- #if UNITY_EDITOR
- if (executing == CanvasUpdate.Prelayout)
- onValueChanged.Invoke(m_IsOn);
- #endif
- }
-
- public virtual void LayoutComplete()
- {}
-
- public virtual void GraphicUpdateComplete()
- {}
-
- protected override void OnEnable()
- {
- base.OnEnable();
- SetToggleGroup(m_Group, false);
- PlayEffect(true);
- }
-
- protected override void OnDisable()
- {
- SetToggleGroup(null, false);
- base.OnDisable();
- }
-
- protected override void OnDidApplyAnimationProperties()
- {
- // Check if isOn has been changed by the animation.
- // Unfortunately there is no way to check if we don�t have a graphic.
- if (graphic != null)
- {
- bool oldValue = !Mathf.Approximately(graphic.canvasRenderer.GetColor().a, 0);
- if (m_IsOn != oldValue)
- {
- m_IsOn = oldValue;
- Set(!oldValue);
- }
- }
-
- base.OnDidApplyAnimationProperties();
- }
-
- private void SetToggleGroup(ToggleGroup newGroup, bool setMemberValue)
- {
- ToggleGroup oldGroup = m_Group;
-
- // Sometimes IsActive returns false in OnDisable so don't check for it.
- // Rather remove the toggle too often than too little.
- if (m_Group != null)
- m_Group.UnregisterToggle(this);
- // At runtime the group variable should be set but not when calling this method from OnEnable or OnDisable.
- // That's why we use the setMemberValue parameter.
- if (setMemberValue)
- m_Group = newGroup;
-
- // Only register to the new group if this Toggle is active.
- if (newGroup != null && IsActive())
- newGroup.RegisterToggle(this);
-
- // If we are in a new group, and this toggle is on, notify group.
- // Note: Don't refer to m_Group here as it's not guaranteed to have been set.
- if (newGroup != null && newGroup != oldGroup && isOn && IsActive())
- newGroup.NotifyToggleOn(this);
- }
-
- /// <summary>
- /// Whether the toggle is currently active.
- /// </summary>
- public bool isOn
- {
- get { return m_IsOn; }
- set
- {
- Set(value);
- }
- }
-
- void Set(bool value)
- {
- Set(value, true);
- }
-
- void Set(bool value, bool sendCallback)
- {
- if (m_IsOn == value)
- return;
-
- // if we are in a group and set to true, do group logic
- m_IsOn = value;
-
- if (m_Group != null && IsActive())
- {
- Debug.Log("m_Group.AnyTogglesOn()"+m_Group.AnyTogglesOn());
- if (m_IsOn || (!m_Group.AnyTogglesOn() && !m_Group.allowSwitchOff))
- {
- Debug.Log("m_IsOn = " + m_IsOn);
- m_IsOn = true;
- m_Group.NotifyToggleOn(this);
- }
- }
-
- // Always send event when toggle is clicked, even if value didn't change
- // due to already active toggle in a toggle group being clicked.
- // Controls like Dropdown rely on this.
- // It's up to the user to ignore a selection being set to the same value it already was, if desired.
- PlayEffect(toggleTransition == ToggleTransition.None);
- if (sendCallback)
- onValueChanged.Invoke(m_IsOn);
- }
-
- /// <summary>
- /// Play the appropriate effect.
- /// </summary>
- private void PlayEffect(bool instant)
- {
- Debug.Log("m_IsOn" + m_IsOn);
- if (graphic == null)
- return;
-
- #if UNITY_EDITOR
- if (!Application.isPlaying)
- {
- graphic.canvasRenderer.SetAlpha(m_IsOn ? 1f : 0f);
- }
- else
- #endif
- {
- graphic.CrossFadeAlpha(m_IsOn ? 1f : 0f, instant ? 0f : 0.1f, true);
- }
- }
-
- /// <summary>
- /// Assume the correct visual state.
- /// </summary>
- protected override void Start()
- {
- PlayEffect(true);
- }
-
- private void InternalToggle()
- {
- if (!IsActive() || !IsInteractable())
- return;
-
- isOn = !isOn;
- }
-
- /// <summary>
- /// React to clicks.
- /// </summary>
- public virtual void OnPointerClick(PointerEventData eventData)
- {
- if (eventData.button != PointerEventData.InputButton.Left)
- return;
- InternalToggle();
- }
-
- public virtual void OnSubmit(BaseEventData eventData)
- {
- InternalToggle();
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。