Unity+Slua实现游戏常用UI组件(一)——滚动表格组件

  • 补充说明
    LScrollView是一个允许内部元素1动态改变大小并自动布局的滚动表格组件
    高度的灵活性必然会有其局限性,比如
    • 代码的复杂度较高,特别是在增加 元素与边界的间隔(padding),元素与元素之间的间隔(gap) 这两个功能之后,布局相关的代码并不能简洁易懂
    • 当某元素不在当前显示范围,而想让组件滚动到该元素所在位置时,因为高度不确定,处理起来不方便,目前的解决方案是先调用SetStartIndex(),再调用SetData(),最终的效果略有瑕疵
      这时回过头来评估下游戏的实际业务,其实游戏中需要滚动表格组件下所有元素动态变化大小是极其少见
    • 1、大部分情况下滚动表格组件的所有元素的大小相同
    • 2、小部分情况下会有多种不同类型的元素
    • 3、极少数情况会要求同一种元素能动态改变大小
      所以我针对前两种情况又提取了两个组件
      如果滚动表格组件下所有元素大小相同的,可以用单元素滚动表格组件
      如果滚动表格组件下有多种不同高度元素的,可以用多元素滚动表格组件
      如果遇到第三种情况,才用滚动表格组件——LScrollView

  1. LScrollView效果展示

  2. 特性
    2.1、创建满足Mask展示的最小数量的元素1,滚动过程中保证元素复用
    2.2、支持垂直(水平)滚动时每一行元素的高(宽)度不相等,但要保证一行(列)的高(宽)度相等
    2.3、支持设置元素与元素之间的间隔(gap),设置元素与ScrollRect中Content的偏移值(padding)
    2.4、滚动到展示内容末尾会有对应事件派发,方便实现数据流的效果(详见LScrollViewDemo的第4个例子)
    2.5、使用者与元素方便进行交互,拓展性良好(详见LScrollViewDemo的第6个例子)

  3. 核心代码:

function LScrollView:_OnValueChanged(value)
   ...
   if not self:_ContentContainMask() then
       while(self:_CanAddAtStart()) do
           self:_RemoveEndOutMask()
           self:_AddAtStart()
       end
       while(self:_CanAddAtEnd()) do
           self:_RemoveStartOutMask()
           self:_AddAtEnd()
       end
   end
end

LScrollView是对UGUI的ScrollRect进行扩展。监听OnValueChanged事件,当滚动之后展示内容(ScrollRect的Content)不足以覆盖Mask时,会检测是否有未显示内容,如果有就插入显示,在插入之前会先检测是否有展示内容超过Mask范围,如果有则回收复用

  1. 注意事项:
    4.1、当垂直滚动中同一行高度不等(或水平滚动同一列宽度不等)时,滚动松手后的惯性运动,会出现突然加速的情况,所以要保证同一行高度一致(或同一列宽度相等)
    4.2、不支持元素与元素之间的间隔为负数的情况,不支持元素与ScrollRect中Content的偏移值为负数的情况。假设前面情况发生,判断元素是否超过Mask显示范围会出问题。游戏中这种情况非常少见,所以我禁止了这种设置
    4.3、游戏界面的逻辑习惯于整体刷新,所以LScrollView只暴露了SetData这个接口用于界面刷新,没有单独刷新某个元素的接口
    4.4、要是使用者希望从某个元素(或许是第一千个元素)开始显示,可以先调用SetStartIndex,再调用SetData
    4.5、当多次SetData时,可能会出现LScrollView显示的第一个元素超过整体数据大小的情况,这时LScrollView会从第一个元素开始显示

  2. 项目地址:
    git地址(Demo下的LScrollView)
    Unity版本:5.6.6

  3. 设计思路:
    6.1、因为不能保证元素的高度一致,或者宽度一致,在最小元素生成的情况下,无法预估ScrollRect中Content的大小,因此Content大小一直维持比Mask的显示内容大一点
    6.2、修改Content的大小会影响滚动的连续性,为了保证连续性,需要修改ScrollRect的两个私有变量,这里实现思路参考了这篇文章,我复制了UGUI的源码,暴露了一个接口给Lua调用
    https://blog.csdn.net/swj524152416/article/details/53483824



  1. 把上图中一个格子称为一个元素 ↩︎ ↩︎

你可能感兴趣的:(unity)