UGUI源码之Selectable

Selectable是Button、InputField、Toggle、ScrollBar、Slider、Dropdown的基类。

Selectable的继承的类与接口如下:

    public class Selectable
        :
        UIBehaviour,
        IMoveHandler,
        IPointerDownHandler, IPointerUpHandler,
        IPointerEnterHandler, IPointerExitHandler,
        ISelectHandler, IDeselectHandler

 

继承自UIBehaviour的函数:

 Awake:获取了一个Graphic组件赋值给m_TargetGraphic。在选择的Transition是Color Tint时,当Selectable的状态变化,会调用Graphic的CrossFadeColor函数,使颜色渐变。在选择的Transition是Sprite Swap时,当Selectable的状态变化,会获取Image(m_TargetGraphic as Image),修改其sprite。

OnEnable:把本实例加入到一个静态的List<Selectable > s_List中,然后设置实例状态,最后调用InternalEvaluateAndTransitionToSelectionState函数(会判断是否是禁用状态,然后调用DoStateTransition函数,根据m_Transition执行对应的过渡效果)。

OnDisable:把本实例从s_List中移除,并且调用InstantClearState函数清除状态。

OnDidApplyAnimationProperties:调用OnSetProperty函数,OnSetProperty函数里最终还是调用InternalEvaluateAndTransitionToSelectionState函数。

OnCanvasGroupChanged:CanvasGroup变化时,会判断CanvasGroup的Interactable是否为false,如果是则break。如果CanvasGroup的ignoreParentGroups为true的话,也break。那么表示Selectable被禁用了。然后调用OnSetProperty函数。

 

继承自IMoveHandler的函数:

OnMove:根据移动方向,导航到下一个Selectable组件。

 

继承自IPointerDownHandler的函数:OnPointerDown:调用EventSystem.current.SetSelectedGameObject(gameObject, eventData)(在EventSystem文字中讲到过这个函数)函数将自身设为选中对象,将isPointerDown设为true,调用EvaluateAndTransitionToSelectionState函数更新状态。

 

继承自IPointerUpHandler的函数:

OnPointerUp:将isPointerDown设为false,调用EvaluateAndTransitionToSelectionState函数更新状态

 

继承自IPointerEnterHandler的函数:OnPointerEnter:将isPointerInside设为true,调用EvaluateAndTransitionToSelectionState函数更新状态。

 

继承自IPointerExitHandler的函数:

OnPointerExit:将isPointerInside设为false,调用EvaluateAndTransitionToSelectionState函数更新状态。

 

继承自ISelectHandler的函数:

OnSelect:将hasSelection设为true,调用EvaluateAndTransitionToSelectionState函数更新状态。

 

继承自OnDeselect的函数:

OnDeselect:将hasSelection设为false,调用EvaluateAndTransitionToSelectionState函数更新状态。

 

讲一下EvaluateAndTransitionToSelectionState和InternalEvaluateAndTransitionToSelectionState函数

      private void EvaluateAndTransitionToSelectionState(BaseEventData eventData)
        {
            if (!IsActive() || !IsInteractable())
                return;

            UpdateSelectionState(eventData);
            InternalEvaluateAndTransitionToSelectionState(false);
        }

通过UpdateSelectionState决定当前状态m_CurrentSelectionState。然后调用InternalEvaluateAndTransitionToSelectionState函数。

 

     private void InternalEvaluateAndTransitionToSelectionState(bool instant)
        {
            var transitionState = m_CurrentSelectionState;
            if (IsActive() && !IsInteractable())
                transitionState = SelectionState.Disabled;
            DoStateTransition(transitionState, instant);
        }

 

会判断是否是禁用状态,然后调用DoStateTransition函数。在DoStateTransition中会根据m_Transition执行对应的过渡效果。

 

     protected virtual void DoStateTransition(SelectionState state, bool instant)
        {
            Color tintColor;
            Sprite transitionSprite;
            string triggerName;

            switch (state)
            {
                case SelectionState.Normal:
                    tintColor = m_Colors.normalColor;
                    transitionSprite = null;
                    triggerName = m_AnimationTriggers.normalTrigger;
                    break;
                case SelectionState.Highlighted:
                    tintColor = m_Colors.highlightedColor;
                    transitionSprite = m_SpriteState.highlightedSprite;
                    triggerName = m_AnimationTriggers.highlightedTrigger;
                    break;
                case SelectionState.Pressed:
                    tintColor = m_Colors.pressedColor;
                    transitionSprite = m_SpriteState.pressedSprite;
                    triggerName = m_AnimationTriggers.pressedTrigger;
                    break;
                case SelectionState.Disabled:
                    tintColor = m_Colors.disabledColor;
                    transitionSprite = m_SpriteState.disabledSprite;
                    triggerName = m_AnimationTriggers.disabledTrigger;
                    break;
                default:
                    tintColor = Color.black;
                    transitionSprite = null;
                    triggerName = string.Empty;
                    break;
            }

            if (gameObject.activeInHierarchy)
            {
                switch (m_Transition)
                {
                    case Transition.ColorTint:
                        StartColorTween(tintColor * m_Colors.colorMultiplier, instant);
                        break;
                    case Transition.SpriteSwap:
                        DoSpriteSwap(transitionSprite);
                        break;
                    case Transition.Animation:
                        TriggerAnimation(triggerName);
                        break;
                }
            }
        }

 

posted on 2019-06-05 14:01  pj2933  阅读(565)  评论(0编辑  收藏  举报

导航