Slider是UGUI的一个组件,使用它可以实现滑动条,算是一个比较常用的组件,它与ScrollBar(参考UGUI内核大探究(十一)ScrollRect与ScrollBar)有些类似,但又不太相同。本文那就分析一下Slider的原理。

按照惯例,附上UGUI源码下载地址。

Slider继承自Selectable,并继承了IDragHandler, IInitializePotentialDragHandler, ICanvasElement三个接口。

Slider重写了OnEnable和OnDisable(调用时机参见Untiy3D组件小贴士(一)OnEnabled与OnDisabled)方法。OnEnable里m_FillRect的Image(m_FillImage)和transform组件及其父对象的RectTransform,并找到m_HandleRect的transform组件及其父对象的RectTransform。

如图1对应Slider,2对应m_FillRect,3对应m_HandleRect。

OnEnable还会调用Set方法设置当前值,并更新表现,也就是:根据当前Value设置m_FillImage的fillAmount(ImageType为Filled,祥参UGUI内核大探究(九)Image与RawImage)或anchorMin和anchorMax(其他ImageType)以及m_HandleRect的anchorMin和anchorMax,体现出来就是滑动条的填充区域和滑动按钮的位置发生了变化。

而OnDisable只是调用DrivenRectTransformTracker类型的m_Tracker的Clear方法。(参考https://docs.unity3d.com/462/Documentation/ScriptReference/DrivenRectTransformTracker.html。)

OnDidApplyAnimationProperties(当应用动画属性后)会判断动画是否影响了表现,将表现修正回来。

OnRectTransformDimensionsChange(当RectTransform维度变化)会更新表现。

OnPointerDown(当鼠标或触摸点下)会判断事件位置是否在m_HandleRect里面,如果在里面,将它转换为m_HandleRect的本地位置,设置它为拖拽的起始点(m_Offset),如果不在,直接调用UpdateDrag将value设置为对应的值。

另外还重写了Selectable的OnMove、FindSelectableOnLeft、FindSelectableOnRight、FindSelectableOnUp和FindSelectableOnDown方法。当方向键按下并与Slideer的方向一致时,便不在导航到下一个Selectable,而是修改value值(加减stepSize),即移动滑动条。

OnDrag是继承自IDragHandler的方法,也会调用UpdateDrag,将时间点转换为本地点,减去m_Offset,除以尺寸得到normalizedValue,normalizedValue的set访问器(参考C#语法小知识(六)属性与索引器)里会将它转化为给value。

OnInitializePotentialDrag是继承自IInitializePotentialDragHandler的方法,它设置事件useDragThreshold为false,即在拖拽事件开始前不需要额外的阈值判断。

Set方法:

        protected virtual void Set(float input, bool sendCallback){// Clamp the inputfloat newValue = ClampValue(input);// If the stepped value doesn't match the last one, it's time to updateif (m_Value == newValue)return;m_Value = newValue;UpdateVisuals();if (sendCallback)m_OnValueChanged.Invoke(newValue);}

ClampValue是将input限定在编辑器里设置的Min Value和Max Value之间。如果value改变,且sendCallback为true,便会发送m_OnValueChanged事件。我们可以在编辑器里添加对这个事件的监听。

当我们在编辑器里设置Slider的Direction时候,我们发现Slider发生了旋转。这就涉及到SetDirection方法:

        public void SetDirection(Direction direction, bool includeRectLayouts){Axis oldAxis = axis;bool oldReverse = reverseValue;this.direction = direction;if (!includeRectLayouts)return;if (axis != oldAxis)RectTransformUtility.FlipLayoutAxes(transform as RectTransform, true, true);if (reverseValue != oldReverse)RectTransformUtility.FlipLayoutOnAxis(transform as RectTransform, (int)axis, true, true);}

当赋值完direction属性的后,再调用axis(Horizontal或Vertical)和reverseValue(反转值)属性会更新。如果axis改变了,调用FlipLayoutAxes翻转坐标轴。如果reverseValue改变了,FlipLayoutOnAxis在轴上翻转(水平翻转或竖直翻转)。这样就只需要根据坐标轴来取值赋值就可以了,不用做复杂的判断。

UGUI内核大探究(十二)Slider相关推荐

  1. UGUI内核大探究(二)执行事件

    UGUI内核大探究(一)EventSystem我们探究了事件系统,其中我们讲到EventSystem可以通过ExecuteEvents这个类来执行事件,那么事件是如何执行的呢?这里涉及到了两个文件Ev ...

  2. UGUI内核大探究(十六)InputField

    InputField是UGUI的重要组件,可以提供文本输入功能,是与用户交互的一个重要手段.我们可以在编辑器里,为OnValueChanged和OnEndEdit两个事件添加监听,这样就可以获得用户输 ...

  3. UGUI内核大探究(十八)Raycaster

    射线其实是属于事件系统,它在EventSystem/Raycasters目录下,有BaseRaycaster.PhysicsRaycaster和Physics2DRaycaster三个类,命名空间也是 ...

  4. UGUI内核大探究(十一)ScrollRect与ScrollBar

    当我们在Unity Editor里创建一个Scroll View的时候含有ScrollRect的对象,它下面还有三个子对象,两个含有ScrollBar组件的子对象是作为滚动条,一个Viewport用于 ...

  5. UGUI内核大探究(九)Image与RawImage

    Image组件是UGUI里最常用的组件(可能没有之一),我们知道其实还有一个RawImage组件.那么二者的区别是什么呢?之前的文章UGUI内核大探究(八)MaskableGraphic中我们提到过, ...

  6. UGUI内核大探究(八)MaskableGraphic

    MaskableGraphic是UGUI的核心组件,它继承自Graphic.MaskableGraphic是一个抽象类,它的派生类有RawImage.Image.Text.顾名思义,MaskableG ...

  7. UGUI内核大探究(十三)Dropdown

    Dropdown(下拉框)可谓是UGUI的集大成者,在Unity Editor里新建一个Dropdown,会随之附赠Text(Label对象).Image(Arrow对象).ScrollRect(Te ...

  8. UGUI内核大探究(一)EventSystem

    2019独角兽企业重金招聘Python工程师标准>>> UGUI是Unity3D官方推出的UI系统,为了更好的使用UGUI,我们就需要去了解它. UGUI代码开源,我们可以从bitb ...

  9. 网上流传的《名侦探柯南》大结局十二种!

    网上流传的<名侦探柯南>大结局十二种! 以下结局 纯属虚构 如有雷同 勿扔鸡蛋 (一)柯南终于打败黑暗组织并找到恢复身体的方法,与小兰共结连理.后来两人有了爱情的结晶--一个男孩,取名为工 ...

最新文章

  1. python3编码转换_Python3编码转换
  2. 堆排序 C++代码实现及思想 排序过程输出 恋上数据结构笔记
  3. 外包物料成本核算时的供应商确定
  4. NIFI使用过程中的invalid component问题解决
  5. 使用Forms Authentication实现用户注册、登录 (三)用户实体替换
  6. 618物流压力怎么扛?
  7. 数据存储技术-专题介绍
  8. 推荐几个好用实用的免费图标素材(好看的icon)
  9. java 将月份、星期转换为英文
  10. C语言五子棋的项目背景,五子棋项目源码!
  11. 【ESP32_8266_WiFi (十四)】ESP8266多任务处理 – Ticker库使用说明
  12. 【Unity3D插件】DoTween插件的简单介绍及示例代码
  13. 请把ios文件解压出来是什么意思_全网电影+美剧+日韩剧(ios+安卓)
  14. 招标过程中如何讲标?
  15. 超好看的3D烟花代码(html+css+js)带音乐
  16. FE内容付费系统响应式(带手机版) v5.46
  17. 2017-2018-1 20162316刘诚昊 实验二 树
  18. 让linux后台持续运行某个程序
  19. php学籍信息管理系统心得_PHP实现简单的学生信息管理系统(web版)
  20. 通过js控制layui选择框checkbox的选中、取消选中,以及使用layui实现全选、取消全选的一种方式

热门文章

  1. 骨牌铺方格java_[ACM_HDU_2046]骨牌铺方格 | 学步园
  2. 印度软件外包凭什么比中国强
  3. 牛客第十场 F.Popping Balloons
  4. qq群邮件html背景音乐,群发HTML格式邮件基础知识
  5. SpringCloud 教程 (二) 服务链路追踪(Spring Cloud Sleuth)
  6. python伪造邮件发件地址_python-SMTPSenderRefused-553,发件人地址未经验证-Django电子邮件表格...
  7. 地铁大数据挖掘之数据预处理——从原始一卡通数据提取城市地铁客流(二)
  8. Spark+Scala建设数仓和数据分析
  9. 关于“上海电信IPTV系统开机广告不能关闭“问题的看法
  10. red hat linux分区,【Red Hat Linux基础】 磁盘分区详细教程