UGUI学习手记-Selectable& Button

版权声明:http://blog.csdn.net/admin_jhon https://blog.csdn.net/Admin_Jhon/article/details/62217453

关于源码

关于源码可以参考这篇博客下载或调试。

Selectable

特性

[AddComponentMenu("UI/Selectable", 70)]  
[ExecuteInEditMode]  
[SelectionBase] 
[DisallowMultipleComponent]  
  1. AddComponentMenu – 为Component菜单添加选项,顺序为70。当点击一个GameObject的AddComponent按钮时,会弹出一个菜单,点击UI选项,就可以看到排在最后一个的就是Selectable。

  2. ExecuteInEditMode – 该组件会在编辑器下执行。

  3. SelectionBase – 标记该对象为选择基本对象。

  4. DisallowMultipleComponent – 不允许一个GameObject上出现同种组件。我们无法为一个对象添加两个Selectable组件,也无法为一个Button对象再添加一个InputField组件。

属性

  • 继承自UIBehaviour,并且继承了7个接口。
    public class Selectable  
        :  
            UIBehaviour,  
            IMoveHandler,  
            IPointerDownHandler, IPointerUpHandler,  
            IPointerEnterHandler, IPointerExitHandler,  
            ISelectHandler, IDeselectHandler  
  • UIBehaviour – 所有UI组件的基类,它被放在EventSystem目录下,除了IsDestroyed以外,其他都是虚函数,我们也可以认为它是事件系统的一部分,它添加了Awake当脚本实例被加载,即AddComponent时)、OnRectTransformDimensionsChange当RectTransform维度变化)等方法来接收来自UnityEngine 的事件。

  • SelectableAwake 时获取了一个Graphic 的组件实例m_TargetGraphicImage组件间接继承自Graphic)。如果我们选择的TransitionColor Tint,当Selectable的状态变化(普通、高亮、按压、禁用)时,会调用m_TargetGraphicCrossFadeColor方法,即将当前图像渐变为指定颜色。

  • OnEnable – 会将该实例添加至Selectable 的静态列表s_List 里(s_List里存放了所有可用的Selectable,用于UI导航的查询),然后设置实例的状态为Normal 或者Highlighted(亦或Disabled)。

  • OnDisable – 将实例清除状态(需要恢复颜色和图片,以及播放Normal 动画),并从s_List 中将该实例移除。

  • OnDidApplyAnimationProperties – (当应用动画属性后),会通过OnSetProperty 方法调用InternalEvaluateAndTransitionToSelectionState,刷新当前状态。

  • OnCanvasGroupChanged – (当CanvasGroup 变化时)里,会判断新的GanvasGroupinteractable,如果GanvasGroupinteractable为false,那么Selectable 本身也就被禁用了。接着,刷新当前状态。

  • 继承自IMoveHandler – 实现OnMove 方法。根据移动方向,导航到下一个Selectable组件。

  • 继承自IPointerDownHandler – 实现OnPointerDown 方法。调用EventSystem.current.SetSelectedGameObject将自己设为当前选中对象(会调用自己的OnSelect和前任对象的OnDeselect),标记isPointerDowntrue 并刷新状态(当isPointerInsideisPointerDown同时为true的时候为Pressed 状态)。

  • 继承自IPointerUpHandler – 实现OnPointerUp方法。标记isPointerDownfalse并刷新状态。

  • 继承自IPointerEnterHandler – 实现OnPointerEnter方法。标记isPointerInsidetrue并刷新状态。

  • 继承自IPointerExitHandler – 实现OnPointerExit方法。标记isPointerInsidefalse并刷新状态。

  • 继承自ISelectHandler – 实现OnSelect方法。标记hasSelectiontrue并刷新状态(hasSelection为true时为Highlighted状态,另外isPointerInside和isPointerDown也是判断Highlighted状态的依据)。

  • 继承自IDeselectHandler – 实现OnDeselect方法。标记hasSelectionfalse并刷新状态。

关于IsHighlighted:

protected bool IsHighlighted(BaseEventData eventData)  
{  
    if (!IsActive())  
    return false;  
    if (IsPressed())  
     return false;  
     bool selected = hasSelection;  
     if (eventData is PointerEventData) 
      {  
          var pointerData = eventData as PointerEventData;  
          selected |=  
           (isPointerDown && !isPointerInside && pointerData.pointerPress == gameObject) // This object pressed, but pointer moved off  
            || (!isPointerDown && isPointerInside && pointerData.pointerPress == gameObject) // This object pressed, but pointer released over (PointerUp event)  
            || (!isPointerDown && isPointerInside && pointerData.pointerPress == null); // Nothing pressed, but pointer is over
       }  
        else  
        {
            selected |= isPointerInside;  
        }
        return selected;  

参数为输入模块传递过来的事件数据,主要用于判断事件响应对象是否是本对象(或者是null)。上述的OnPointerDown等方法是通过EvaluateAndTransitionToSelectionState方法评估并刷新状态。在这个方法里,UpdateSelectionState调用IsPressedIsHighlighted判断当前状态。InternalEvaluateAndTransitionToSelectionState判断当前组件是否被禁用,然后调用DoStateTransition方法。

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;
         }
    }
}

根据状态设置颜色、图片或动画名称,再通过StartColorTweenDoSpriteSwapTriggerAnimation方法在UI上体现出状态的改变。

Button

Button继承自Selectable并额外继承了IPointerClickHandlerISubmitHandler两个接口。

它还添加了一个UnityEvent类型的事件onClickonClick事件可以添加用户自定义的监听,具体方法可以通过编辑器添加也可以通过onClick.AddListener添加。就是相对于Selectable添加了响应点击和确认事件的接口,并且开放了可添加用户自定义监听的onClick事件。

  • OnPointerClick会调用Press方法来回调onClick

  • OnSubmit也会调用Press方法,并切换状态为Pressed,并开启协程调用OnFinishSubmit,让状态渐变为当前状态(通过UpdateSelectionState获得的状态)。

最后

Selectable的作用在于提供了基于鼠标事件的四种状态变化。一方面,为Button、Dropdown等派生类提供了基础的逻辑,另一方面,我们也可以根据Selectable派生出新的自定义组件。

猜你喜欢

转载自blog.csdn.net/Admin_Jhon/article/details/62217453
今日推荐