1. 程式人生 > 實用技巧 >雙滑動列表實現

雙滑動列表實現

推薦閱讀:

在專案中,我們經常會使用到列表來展示獎勵或者任務,通常我們遇見的都是很簡單的單滑動列表,如下案列:

這不,最近有個新功能,需要展示一個進度滑動列表和一個獎勵滑動列表,如下案例

首先想到的是將進度條和獎勵弄在一個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