Runtime类图分析
Selectable
Selectable是UGUI的核心组件,除了最常用的Button,它还是Scrollbar、Dropdown、Slider、Toggle、InputField这些组件的基类。
它的作用在于提供了基于鼠标事件的四种状态变化。一方面,为Button、Dropdown等派生类提供了基础的逻辑,另一方面,我们也可以根据Selectable派生出新的自定义组件。
在Selectable之前,我们看到,它被添加了四个属性:
[AddComponentMenu("UI/Selectable", 70)]
[ExecuteInEditMode] 运行在编辑器模式下
[SelectionBase] 标记此对象为基本选择对象
[DisallowMultipleComponent] 一个Game Object上不允许有多个Selectable组件,同样我们也无法为一个Button组件添加一个InputFiled组件。
关键方法分析
接口方法
继承自IMoveHandler的OnMove方法。调用 void Navigate(AxisEventData eventData, Selectable sel)根据移动方向,导航到下一个Selectable组件。
继承自IPointerDownHandler的OnPointerDown方法。调用EventSystem.current.SetSelectedGameObject将自己设为当前选中对象(会调用自己的OnSelect和旧对象的OnDeselect),标记isPointerDown为true并调用EvaluateAndTransitionToSelectionState判断当前组件是否为显示和启用状态,如果是那么调用DoStateTransition(SelectionState state, bool instant)刷新状态,为Pressed状态。在DoStateTransition方法中根据当前的状态做数据的同步,并根据Transition的不同设置不同的表现:
case Transition.ColorTint:
StartColorTween(tintColor * m_Colors.colorMultiplier, instant);
break;
case Transition.SpriteSwap:
DoSpriteSwap(transitionSprite);
break;
case Transition.Animation:
TriggerAnimation(triggerName);
break;
继承自IPointerUpHandler需要实现OnPointerUp方法。标记isPointerDown为false并刷新状态。
继承自IPointerEnterHandler需要实现OnPointerEnter方法。标记isPointerInside为true并刷新状态。
继承自IPointerExitHandler需要实现OnPointerExit方法。标记isPointerInside为false并刷新状态。
继承自ISelectHandler需要实现OnSelect方法。标记hasSelection为true并刷新状态(hasSelection为true时为Highlighted状态,另外isPointerInside和isPointerDown也是判断Highlighted状态的依据,IsHighlighted()方法判断是否是高亮状态)。
继承自IDeselectHandler需要实现OnDeselect方法。标记hasSelection为false并刷新状态。
基类方法
继承自UIBehaviour的几个方法
- Awake方法获取一个Graphic组件实例m_TargetGraphic,如果选择的Transition是Color Tint,当Selectable的状态变化(普通、高亮、按压、禁用)时,会调用m_TargetGraphic.CrossFadeColor方法,将当前颜色渐变成指定颜色。
- OnEnable方法中,会把实例本身加入到Selectable的静态列表s_List 中,然后设置实例的状态为Normal或者Highlighted。
- OnDisable方法中,会把实例本身从Selectable的静态列表s_List 中移除,并将实例状态清除重置,包括恢复颜色和图片,还有播放normal动画。
- 当动画的属性发生改变后,会调用OnDidApplyAnimationProperties方法,在方法中调用OnSetProperty方法的中的DoStateTransition方法,刷新状态。
- 当CanvasGroup发生变化时,会调用OnCanvasGroupChanged方法,会判断新的GanvasGroup的interactable,如果GanvasGroup的interactable为false,那么Selectable本身也就被禁用了。接着,刷新当前状态。
其他方法
IsInteractable 是否可交互
InstantClearState 立刻清空当前的状态,重置刷新
RemoveInvalidSelectables 移除所有可选择对象的列表无效的项,为空或将要被移除的项
FindSelectablee(Vector3 dir)
FindSelectableOnLeft
FindSelectableOnRight
FindSelectableOnUp
FindSelectableOnDown
传入一个方向,查找一个最近的Selectable物体
Vector3 GetPointOnRectEdge(RectTransform rect, Vector2 dir) 指定dir方向的直线在rect内的交点
Select 让这个物体处于选中状态
bool IsHighlighted(BaseEventData eventData)
参数是输入模块传入的事件数据,主要判断事件响应对象是否是本对象,或者是为null。然后会跟据hasSelection与isPointerInside和isPointerDown做或运算,处理不同的状态
- 对象被按下,但是指针移开了
- 对象被按下,但是指针松开了
- 没有对象被按下,但是指针在对象上面
重要属性和字段分析
private static List<Selectable> s_List = new List<Selectable>();
维护了一个在场景中处于激活状态的所有可选择对象的列表
Navigation m_Navigation
Transition m_Transition
Selectable的变化模式
None,
ColorTint,
SpriteSwap,
Animation
ColorBlock m_Colors
当Selectable的变化模式选择为ColorTint时,管理各种颜色变化
SpriteState m_SpriteState
当Selectable的变化模式选择为SpriteState 时,管理各种Image的Sprite切换
AnimationTriggers m_AnimationTriggers
当Selectable的变化模式选择为AnimationTriggers 时,管理各种动画切换
Graphic m_TargetGraphic
颜色变化和图片变化时的目标Image
Button
Button继承了Selectable,IPointerClickHandler,ISubmitHandler
核心字段
ButtonClickedEvent : UnityEvent 类型的事件onClick,onClick事件可以通过onClick.AddListener方法,添加用户自定义的监听
重要方法
OnPointerClick方法,会通过Press方法回调onClick。
OnSubmit方法,也会调用Press方法回调onClick,并设置状态为Pressed,开启协程OnFinishSubmit,让状态渐变为当前状态(通过UpdateSelectionState获得的状态)。
可以看出Button就是相对于Selectable添加了响应点击和确认事件的接口,并且开放了可添加用户自定义监听的onClick事件