【UI界面开发】基本组件——滑杆

摘要

  • 本文章是关于UGUI组件Slider的学习和总结
  • 为了更好的学习,将从“自制模仿”的角度去分析该组件,并在最后自制一个简易的Slider作为结尾。

Slider基本要素

  • 作为滑杆,它的主要特点在于滑动。因此它必然有一个支持拖拽的控件,并且拖拽是受到规则限制的,不能随意拖拽的。
  • 从视效上看,滑杆必须能体现当前的滑动量,因此需要有一个支持动态改变长度的图片。
  • 而从实际功能上看,它还要能表示当前的滑动幅度值。Slider和Toggle不同,Toggle是表现二元值的控件。而Slider则是可以表现连续值的控件。如果把完全关闭设置为0,完全开启设置为1,那么Slider没有滑动时为0,滑动过程中值从0到1渐变。

UGUI之Slider

Unity预设Slider组成分析

在这里插入图片描述

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

Inspector窗口参数

在这里插入图片描述

  • 简单观察可知我们可以把参数分成上下两部分,上半部分是与Button相同的参数,下半部分则是Slider特有的参数
  • 查看上半部分target Graphic可知其渲染的对象是Handle,即实现拖拽交互的UI。因此该UI具有和Button相同的视效表现。
  • 查看下半部分FillRectHandleRect两个参数,它们都是Rect Transform类型,这两个参数主要在于控制指定UI,在交互过程中RectTransform的变化。
  • Direction则是设置交互的方式
  • MinValueMaxValue则是设置在完全没有滑动时的值与滑动到底时的值
  • Whole Numbers是一个布尔值,它表示值是否为整数值,如果它为true那么下方的value只能表现为整数。如果与此同时min为0。max为1,那么value就会变成0/1二元值
  • value会根据滑动幅度以及上方三个参数的设置进行动态变化,该值可以被外界捕获

Slider常用成员

  1. value:浮点型属性,可以获取当前值或设置新值,其中设置新值后UI滑动表现也会跟着改变
  2. 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)
        {
            //更新滑杆的位置
            //计算当前滑杆占比
            //根据占比设置新的value值
            //更新填充物的长度以及位置
        }
        #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
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值