UGUI源码解析(七)Selectable与Button

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq826364410/article/details/88137908

1、Selectable

Selectable是UGUI的核心组件,除了最常用的Button,它还是Scrollbar、Dropdown、Slider、Toggle、InputField这些组件的基类。

在Selectable之前,我们看到,它被添加了四个属性:

[AddComponentMenu("UI/Selectable", 70)]

[ExecuteInEditMode] 运行在编辑器模式下

[SelectionBase] 标记此对象为基本选择对象

[DisallowMultipleComponent] 一个Game Object上不允许有多个Selectable组件,同样我们也无法为一个Button组件添加一个InputFiled组件。

Selectable继承自UIBehaviour,并且继承了7个接口。

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

UIBehaviour

是所有UI组件的基类,继承了MonoBehaviour,它被放在EventSystem目录下,除了IsDestroyed以外,其他都是虚函数,我们也可以认为它是事件系统的一部分,它添加了Awake(当脚本实例被加载,即AddComponent时)、OnRectTransformDimensionsChange(当RectTransform尺寸变化)等方法来接收来自UnityEngine的事件。

Selectable维护了一个在场景中处于激活状态的所有可选择对象的列表:

private static List<Selectable> s_List = new List<Selectable>();

Selectable继承UIBehaviour的几个接口

  • Selectable的Awake()方法获取一个Graphic组件实例m_TargetGraphic,如果选择的Transition是Color Tint,当Selectable的状态变化(普通、高亮、按压、禁用)时,会调用m_TargetGraphic.CrossFadeColor方法,将当前颜色渐变成指定颜色。
  • OnEnable方法中,会把实例本身加入到Selectable的静态列表s_List 中,然后设置实例的状态为Normal或者Highlighted。
  • OnDisable方法中,会把实例本身从Selectable的静态列表s_List 中移除,并将实例状态清除重置,包括恢复颜色和图片,还有播放normal动画。
  • 当动画的属性发生改变后,会调用OnDidApplyAnimationProperties方法,在方法中调用OnSetProperty方法的InternalEvaluateAndTransitionToSelectionState方法中的DoStateTransition方法,刷新状态。
  • 当CanvasGroup发生变化时,会调用OnCanvasGroupChanged方法,会判断新的GanvasGroup的interactable,如果GanvasGroup的interactable为false,那么Selectable本身也就被禁用了。接着,刷新当前状态。

然后我们看Selectable继承的其他几个接口

  1. 继承自IMoveHandler需要实现OnMove方法。根据移动方向,导航到下一个Selectable组件。
  2. 继承自IPointerDownHandler需要实现OnPointerDown方法。调用EventSystem.current.SetSelectedGameObject将自己设为当前选中对象(会调用自己的OnSelect和旧对象的OnDeselect),标记isPointerDown为true并刷新状态(当isPointerInside和isPointerDown同时为true的时候,为Pressed状态,IsPressed()方法判断是否为Pressed状态)。
  3. 继承自IPointerUpHandler需要实现OnPointerUp方法。标记isPointerDown为false并刷新状态。
  4. 继承自IPointerEnterHandler需要实现OnPointerEnter方法。标记isPointerInside为true并刷新状态。
  5. 继承自IPointerExitHandler需要实现OnPointerExit方法。标记isPointerInside为false并刷新状态。
  6. 继承自ISelectHandler需要实现OnSelect方法。标记hasSelection为true并刷新状态(hasSelection为true时为Highlighted状态,另外isPointerInside和isPointerDown也是判断Highlighted状态的依据,IsHighlighted()方法判断是否是高亮状态)。
  7. 继承自IDeselectHandler需要实现OnDeselect方法。标记hasSelection为false并刷新状态。

bool IsHighlighted(BaseEventData eventData)

参数是输入模块传入的事件数据,主要判断事件响应对象是否是本对象,或者是为null。然后会跟据hasSelection与isPointerInside和isPointerDown做或运算,处理不同的状态

  1. 对象被按下,但是指针移开了
  2. 对象被按下,但是指针松开了
  3. 没有对象被按下,但是指针在对象上面

上述的OnPointerDown等方法是通过EvaluateAndTransitionToSelectionState方法评估并刷新状态。在这个方法里,UpdateSelectionState调用IsPressed和IsHighlighted判断当前状态。InternalEvaluateAndTransitionToSelectionState判断当前组件是否被禁用,然后调用DoStateTransition方法。根据状态设置颜色、图片或动画名称,再通过StartColorTween、DoSpriteSwap或TriggerAnimation方法在UI上体现出状态的改变。

Selectable的作用

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

2、Button

Button继承了Selectable,IPointerClickHandler,ISubmitHandler,还添加了一个UnityEvent类型的事件onClick,onClick事件可以通过onClick.AddListener方法,添加用户自定义的监听。

OnPointerClick方法,会通过Press方法回调onClick。

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

可以看出Button就是相对于Selectable添加了响应点击和确认事件的接口,并且开放了可添加用户自定义监听的onClick事件。

猜你喜欢

转载自blog.csdn.net/qq826364410/article/details/88137908
今日推荐