Fork me on GitHub

双滑动列表实现

推荐阅读:

在项目中,我们经常会使用到列表来展示奖励或者任务,通常我们遇见的都是很简单的单滑动列表,如下案列:

这不,最近有个新功能,需要展示一个进度滑动列表和一个奖励滑动列表,如下案例

首先想到的是将进度条和奖励弄在一个item上面,但是现在问题来了,看看美术给的图

由于边角是圆角的,直接用的话会出现以下情况:

尝试一

为了方便,便考虑在不考虑修改美术资源的情况下,来实现功能。于是我才用了另一种方案:
考虑使用两个循环列表实现,为了不造成卡顿,减少内存消耗等,还是采用无限列表来实现:
新建两个ScrollView,分别为进度滑动列表和奖励滑动列表,命名为::left和right

滑动实现方法:一个无限列表位置改变带动另一个位置改变:

function base.updaterender(go, index)
    local posRigth = ui.list.gameObject.transform.localPosition
    local posLeft = ui.proglist.gameObject.transform.localPosition
    ui.proglist.gameObject.transform.localPosition = Vector2.New(posLeft.x,posRigth.y)
end

运行效果发现:右侧无限列表带动左边滑动,左边的滑动列表会有明显的滞后感,而且最后停留的位置也会有很大的偏差,至此,此方法行不通,考虑下一种方法.

尝试二

新建一个ScrollView,该Content下面包含两个无限列表:left和right

运行发现没有问题,但是在自以为快要完成功能时发现了问题:当需要指定滑动到某个item时,会造成如下情况:

观察发现,ScrollView/Viewport/Content位置正确,rig话题,left位置正确,但是left和right里面的item位置回到了初始值(即:跑到了最顶端),造成这样的现象是无限列表代码里,每次刷新,会将item位置重置。为了不修改无限列表代码(因为项目很多地方在用,修改了其他地方可能会出现bug),考虑其他方式。在尝试了很多方式后未果,突发奇想,是否可以用一个动画来滑动到指定问题。于是尝试一番之后发现,完美!!!至此,此功能终于解决了~~

local function SliderIdx()
    local idx = FindCanGetIdx()--需要滑动到的item下标
    local pos = ui.content.transform.localPosition
    local posY
    if idx then
        posY = (idx-1)*111.35
        ui.content.gameObject.transform.localPosition = Vector2.New(0, 0)
        ui.content.gameObject.transform:DOLocalMove(Vector2.New(0, posY), 0.8, false):SetEase(Ease.Linear):Play()
    else
        ui.content.transform.localPosition = Vector2.New(ui.content.transform.localPosition.x,0)
    end
end

尝试三

问题解决了,可以考虑下修改美术资源,将进度和奖励整合在一个item上实现,打开在线ps,剪裁掉两边的圆角,成品如下:

这个方法ui表现没有问题,但是在进度计算又遇到问题了,开始的想法是每个进度=当前完成/当前需要,结果发现,在出现如下现象:

这种低级错误我就不多说了,在座各位都比我优秀。
然后判断当前完成与上一进度的大小;当前完成与下一进度的大小;当前完成与当前进度的大小,然后单独处理。这样发现,本来清晰的思路写着写着就混乱了,于是又才用另一种思路计算,首先计算当前点的上方进度,然后再计算下方进度:

--haveExp:当前拥有的
--ui.proto[index-1].exp:上一个item需要达到的
--ui.proto[index].exp:当前item需要达到的
--ui.proto[index+1].exp:下一个item需要达到的
--topSlider:上方进度
--botSlider:下方进度
-- 上面
local last = ui.proto[index-1] and ui.proto[index-1].exp or 0
if (haveExp - last) <= 0 then
    topSlider.value = 0 
elseif (haveExp - ui.proto[index].exp) >= 0 then
    topSlider.value = 1
else
    local total = (haveExp - last) / (ui.proto[index].exp - last) 
    topSlider.value = math.max(total-0.5,0)
end

--下面
if ui.proto[index+1] then
    local _next = ui.proto[index+1].exp
    if (ui.proto[index].exp - haveExp) >= 0  then
        botSlider.value = 0
    else
        local total = (haveExp - ui.proto[index].exp) / ( _next - ui.proto[index].exp) 
        if total >= 0.5 then
            botSlider.value = 1
        else
            botSlider.value = math.max(total,0)*2
        end  
    end
end
posted @ 2020-07-31 17:13  爱上游戏开发  阅读(270)  评论(0编辑  收藏  举报
 >>>转载请注明出处