摘要
- 本文章是关于UGUI组件Slider的学习和总结
- 为了更好的学习,将从“自制模仿”的角度去分析该组件,并在最后自制一个简易的Slider作为结尾。
Slider基本要素
- 作为滑杆,它的主要特点在于滑动。因此它必然有一个支持拖拽的控件,并且拖拽是受到规则限制的,不能随意拖拽的。
- 从视效上看,滑杆必须能体现当前的滑动量,因此需要有一个支持动态改变长度的图片。
- 而从实际功能上看,它还要能表示当前的滑动幅度值。Slider和Toggle不同,Toggle是表现二元值的控件。而Slider则是可以表现连续值的控件。如果把完全关闭设置为0,完全开启设置为1,那么Slider没有滑动时为0,滑动过程中值从0到1渐变。
UGUI之Slider
Unity预设Slider组成分析

- 以上是Slider的展开图。通过观察可以得知,Slider,FillArea,HandleSliderArea是不参与图形渲染的组件,其中FillArea和HandleSliderArea的主要目的是在于Rectransform的自适应设置
- Background是Slider的底部图片,而Fill则是用于表现滑动幅度的图片。Handle则是参与拖拽事件的图片
- 从实际交互体验来看,拖动滑动柄时,滑动柄和填充图片是通过改变拉伸方案以及设置锚点Anchor来实现移动的
Inspector窗口参数

- 简单观察可知我们可以把参数分成上下两部分,上半部分是与Button相同的参数,下半部分则是Slider特有的参数
- 查看上半部分target Graphic可知其渲染的对象是Handle,即实现拖拽交互的UI。因此该UI具有和Button相同的视效表现。
- 查看下半部分FillRect和HandleRect两个参数,它们都是Rect Transform类型,这两个参数主要在于控制指定UI,在交互过程中RectTransform的变化。
- Direction则是设置交互的方式
- MinValue和MaxValue则是设置在完全没有滑动时的值与滑动到底时的值
- Whole Numbers是一个布尔值,它表示值是否为整数值,如果它为true那么下方的value只能表现为整数。如果与此同时min为0。max为1,那么value就会变成0/1二元值
- value会根据滑动幅度以及上方三个参数的设置进行动态变化,该值可以被外界捕获
Slider常用成员
- value:浮点型属性,可以获取当前值或设置新值,其中设置新值后UI滑动表现也会跟着改变
- onValueChange:委托,可以添加事件监听,其中必须带有浮点型参数作为value的输入
自制Slider
- 仔细观察Slider的交互过程,可以发现填充图片和拖拽杆的移动是通过不断更新锚点并保持anchorPosition来实现的。具体过程比较复杂。我们则采用更为简单的方式:修改长度和横坐标(这意味着不做多样的拖拽布局如从上到下的滑杆等)
- 我们知道Slider只有父物体拥有Slider组件来实现包括拖拽在内的各种交互行为。而滑杆等都是没有特殊设置的存粹的图片。这说明它的内在实现重写了底层的射线检测逻辑。这里我们则利用射线检测可以穿透父物体的特点,将包括父物体在内的不需要接收射线检测的UI的Raycast Target设置为false,只保证只有滑杆能被检测到,这样就能使得仅滑杆能够表现出Button的交互视效,并为拖拽功能提供支持。
- 因为Slider涉及到较为复杂的RectTransform的知识点,因此这里仅给出部分实现。
public class CSlider : MonoBehaviour, IPointerEnterHandler, IPointerUpHandler, IPointerExitHandler, IPointerDownHandler, IPointerClickHandler,
IDragHandler
{
#region Inspector Setting
[SerializeField] private bool interactivable;
[SerializeField] private Image targetImage;
[SerializeField] private Text targetText;
[SerializeField] private Color normalColor;
[SerializeField] private Color highlightColor;
[SerializeField] private Color pressedColor;
[SerializeField] private Color selectColor;
[SerializeField] private Color disableColor;
[SerializeField] private RectTransform fillRect;
[SerializeField] private RectTransform handleRect;
[SerializeField] private float minValue;
[SerializeField] private float maxValue;
[SerializeField] private bool wholeNumebrs;
[SerializeField] private float value;
#endregion
#region callBack Methods
private void Awake()
{
if (interactivable)
{
if (targetImage != null)
targetImage.color = normalColor;
if (targetText != null)
targetText.color = normalColor;
}
else
{
if (targetImage != null)
targetImage.color = disableColor;
if (targetText != null)
targetText.color = disableColor;
}
}
public void OnPointerEnter(PointerEventData eventData)
{
if (!Interactivable) return;
if (targetImage != null)
targetImage.color = highlightColor;
if (targetText != null)
targetText.color = highlightColor;
}
public void OnPointerExit(PointerEventData eventData)
{
if (!Interactivable) return;
if (targetImage != null)
targetImage.color = normalColor;
if (targetText != null)
targetText.color = normalColor;
}
public void OnPointerDown(PointerEventData eventData)
{
if (!Interactivable) return;
if (targetImage != null)
targetImage.color = pressedColor;
if (targetText != null)
targetText.color = pressedColor;
}
public void OnPointerUp(PointerEventData eventData)
{
if (!Interactivable) return;
if (targetImage != null)
targetImage.color = selectColor;
if (targetText != null)
targetText.color = selectColor;
}
public void OnPointerClick(PointerEventData eventData)
{
onClickEvent?.Invoke(value);
}
public void OnDrag(PointerEventData eventData)
{
}
#endregion
#region code read-in references
public Action<float> onClickEvent { set; get; }
public bool Interactivable { set => interactivable = value; get => interactivable; }
public Image TargetImage { set => targetImage = value; get => targetImage; }
public Text TargetText { set => targetText = value; get => targetText; }
public Color NormalColor { set => normalColor = value; get => normalColor; }
public Color HighlightColor { set => highlightColor = value; get => highlightColor; }
public Color PressedColor { set => pressedColor = value; get => pressedColor; }
public Color SelectColor { set => selectColor = value; get => selectColor; }
public Color DisableColor { set => disableColor = value; get => disableColor; }
public RectTransform FillRect { set => fillRect = value; get => fillRect; }
public RectTransform HandleRect { set => handleRect = value; get => handleRect; }
public float MinValue { set => minValue = value; get => minValue; }
public float MaxValue { set => maxValue = value; get => maxValue; }
#endregion
}