From 4b4049e938cc78f4b6e04bb5b039c8d27cc2dde6 Mon Sep 17 00:00:00 2001 From: gaoxin Date: Tue, 29 Dec 2020 19:25:25 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90scrollCycleView=E3=80=91=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../~Lua/View/ScrollCycleView.lua | 248 ++++++++++++------ 1 file changed, 164 insertions(+), 84 deletions(-) diff --git a/Assets/ManagedResources/~Lua/View/ScrollCycleView.lua b/Assets/ManagedResources/~Lua/View/ScrollCycleView.lua index 3b560cfea6..ea046a27c3 100644 --- a/Assets/ManagedResources/~Lua/View/ScrollCycleView.lua +++ b/Assets/ManagedResources/~Lua/View/ScrollCycleView.lua @@ -3,13 +3,19 @@ local this = ScrollCycleView local reverse = table.reverse +local function playGoAnim(self, go) + if self.isPlayAnim then + go.transform.localScale = Vector3.zero + go.transform:DOScale(Vector3.one*1, 0.2) + end +end + --表循环移动算法 local function move(list, k) k = k%#list if k == 0 then return end - reverse(list, 1, #list-k) reverse(list, #list-k+1, #list) reverse(list, 1, #list) @@ -23,6 +29,7 @@ local function SetUpdate(self, index, item) end self.updateFunc(index, item.go) self.goItemDataRefList[item.go] = index + playGoAnim(self, item.go) else if item.isActive then item.isActive = false @@ -40,7 +47,7 @@ local function ItemListOffset(self, offset) for i=1, self.itemCount do curRound = (i <= order and 1 or 0) + round if curRound > 0 then - newIndex = self.itemCount * curRound + self.dataIndex + i + newIndex = self.itemCount * curRound + self.dataLine + i go = self.cellItemList[j][i] go.tran.anchoredPosition = go.tran.anchoredPosition + self.offsetV2 * curRound SetUpdate(self, j + (newIndex - 1) * self.fixedCount, go) @@ -50,8 +57,9 @@ local function ItemListOffset(self, offset) for i=1, self.itemCount do curRound = (i <= order and 1 or 0) + round if curRound > 0 then - newIndex = 1 - self.itemCount * (curRound - 1) + self.dataIndex - i + newIndex = 1 - self.itemCount * (curRound - 1) + self.dataLine - i i = self.itemCount - i + 1 + print(j, i) go = self.cellItemList[j][i] go.tran.anchoredPosition = go.tran.anchoredPosition - self.offsetV2 * curRound SetUpdate(self, j + (newIndex - 1) * self.fixedCount, go) @@ -64,9 +72,9 @@ end local function SetItemIndex(self, curIndex) curIndex = math.clamp(curIndex, 0, self.maxOffset) - if curIndex ~= self.dataIndex then - ItemListOffset(self, curIndex - self.dataIndex) - self.dataIndex = curIndex + if curIndex ~= self.dataLine then + ItemListOffset(self, curIndex - self.dataLine) + self.dataLine = curIndex end end @@ -112,7 +120,9 @@ local function SetPosition(self, dv2) end local function OnBeginDrag(self, Pointgo, data) + if not self.isCanDrag then return end if not self.dataList then return end + self.isBeginDrag = true self.moveTween.enabled = true self.moveTween.Momentum = Vector3.zero self.moveTween.IsUseCallBack = false @@ -120,6 +130,7 @@ local function OnBeginDrag(self, Pointgo, data) end local function OnDrag(self, Pointgo, data) + if not self.isBeginDrag then return end if not self.dataList then return end self.moveTween:LerpMomentum(data.delta) SetPosition(self, data.delta) @@ -127,10 +138,12 @@ local function OnDrag(self, Pointgo, data) end local function OnEndDrag(self, Pointgo, data) + if not self.isBeginDrag then return end if not self.dataList then return end SetPosition(self, data.delta) self.moveTween.IsUseCallBack = true data:Use() + self.isBeginDrag = false end local function OnMoveEnd(self) @@ -139,10 +152,10 @@ local function OnMoveEnd(self) if self.itemDis < 0 then self.tmpTween = self.dragGOTran:DOAnchorPosY(0,0.3,false) else - if fv2.y < 0 and self.dataIndex == 0 then + if fv2.y < 0 and self.dataLine == 0 then self.tmpTween = self.dragGOTran:DOAnchorPosY(0,0.3,false) end - if fv2.y > self.itemDis and self.dataIndex == self.maxOffset then + if fv2.y > self.itemDis and self.dataLine == self.maxOffset then self.tmpTween = self.dragGOTran:DOAnchorPosY(self.itemDis,0.3,false) end end @@ -150,10 +163,10 @@ local function OnMoveEnd(self) if self.itemDis < 0 then self.tmpTween = self.dragGOTran:DOAnchorPosX(0,0.3,false) else - if fv2.x > 0 and self.dataIndex == 0 then + if fv2.x > 0 and self.dataLine == 0 then self.tmpTween = self.dragGOTran:DOAnchorPosX(0,0.3,false) end - if fv2.x < -self.itemDis and self.dataIndex == self.maxOffset then + if fv2.x < -self.itemDis and self.dataLine == self.maxOffset then self.tmpTween = self.dragGOTran:DOAnchorPosX(-self.itemDis,0.3,false) end end @@ -184,10 +197,18 @@ function ScrollCycleView:InitComponent() self.OnEndDragNew= function(p,d) OnEndDrag(self,p,d) end + -- self.trigger = Util.GetEventTriggerListener(self.gameObject) + -- self.trigger.onBeginDrag = self.trigger.onBeginDrag + self.OnBeginDragNew + -- self.trigger.onDrag = self.trigger.onDrag + self.OnDragNew + -- self.trigger.onEndDrag = self.trigger.onEndDrag + self.OnEndDragNew self.trigger = Util.GetEventTriggerListener(self.gameObject) - self.trigger.onBeginDrag = self.trigger.onBeginDrag + self.OnBeginDragNew - self.trigger.onDrag = self.trigger.onDrag + self.OnDragNew - self.trigger.onEndDrag = self.trigger.onEndDrag + self.OnEndDragNew + self.isCanDrag = true + self.isBeginDrag = false + self.trigger.onBeginDrag = self.trigger.onBeginDrag + function (p,d) OnBeginDrag(self,p,d) end + self.trigger.onDrag = self.trigger.onDrag + function (p,d) OnDrag(self,p,d) end + self.trigger.onEndDrag = self.trigger.onEndDrag + function (p,d) OnEndDrag(self,p,d) end + + self.rectTransform = self.gameObject:GetComponent("RectTransform") self.dragGO = Util.GetGameObject(self.gameObject, "grid") self.dragGOTran = self.dragGO:GetComponent("RectTransform") @@ -276,11 +297,12 @@ function ScrollCycleView:OnOpen(itemGO, scrollBar, scrollSizeDeltaV2, dragType, end end -function this:SetData(dataList, updateFunc) +function this:SetData(dataList, updateFunc, isTop, noAnim) self.dataList = dataList --传入的数据列表 self.updateFunc = updateFunc --刷新回调,返回数据列表的索引和对应预设 self.dataCount = #dataList - + self.isPlayAnim = not noAnim + if self.dragType == 1 then self.itemDis = self.itemHeight * math.ceil(self.dataCount / self.fixedCount) + self.spacing.y - self.rectTransform.sizeDelta.y self.maxOffset = math.max(math.ceil(self.dataCount / self.fixedCount) - self.itemCount, 0) @@ -296,60 +318,124 @@ function this:SetData(dataList, updateFunc) self.tmpTween = nil end - local oldIndex = self.dataIndex - local oldPos = self.dragGOTran.anchoredPosition - self.dataIndex = 0 - self.dragGOTran.anchoredPosition = Vector2.New(0, 0) - local index, item - for j=1, self.fixedCount do - for i=1, self.itemCount do - item = self.cellItemList[j][i] - index = j+(i-1)*self.fixedCount + -- 判断是否回到顶部,否则保持不动 + if isTop then + self:SetShow(1) + else + local showIndex = self:CalShowIndex() + self:SetShow(showIndex) + end +end - if not item.go and index <= self.dataCount then - local go = newObject(self.item) - go.name = "item"..index - go.transform:SetParent(self.dragGO.transform) - go.transform.localScale = Vector3.one - go.transform.localPosition = Vector3.zero - go:SetActive(false) +-- 获取位置 +function this:CalShowIndex() + local index = 1 + if self.dragType == 1 then + index = math.abs(self.dragGOTran.anchoredPosition.y/self.itemHeight) * self.fixedCount + elseif self.dragType == 2 then + index = math.abs(self.dragGOTran.anchoredPosition.x/self.itemWidth) * self.fixedCount + end + return index +end - local tran = go:GetComponent("RectTransform") - tran.anchorMin = Vector2.New(0, 1) - tran.anchorMax = Vector2.New(0, 1) - - item.go = go - item.tran = tran - end - - if item.go then - if self.dragType == 1 then - item.tran.anchoredPosition = Vector2.New(self.itemWidth * (j-1), (0.5-i) * self.itemHeight) - else - item.tran.anchoredPosition = Vector2.New((i-0.5) * self.itemWidth, self.itemHeight * (1-j)) - end - self.goItemList[index] = item.go - end - SetUpdate(self, index, item) +function this:SetShow(showIndex) + -- 记录旧位置 + local oldLine = self.dataLine or 0 + -- 计算目标数据位置 + local itemOffset = math.ceil(showIndex / self.fixedCount) - 1 + self.dataLine = math.clamp(itemOffset, 0, self.maxOffset) + self.showLine = self.dataLine + -- 计算滚动列表的位置 + if self.itemDis > 0 then + if self.dragType == 1 then + self.dragGOTran.anchoredPosition = Vector2.New(0, math.clamp(self.itemHeight * itemOffset, 0, self.itemDis)) + elseif self.dragType == 2 then + self.dragGOTran.anchoredPosition = Vector2.New(math.clamp(-self.itemWidth * itemOffset, -self.itemDis, 0), 0) end + else + self.dragGOTran.anchoredPosition = Vector2.New(0, 0) end - if self.scrollBar then - if self.dragType == 1 then - self.scrollBar.size = self.rectTransform.sizeDelta.y / (self.itemHeight * math.ceil(self.dataCount / self.fixedCount) + self.spacing.y) - elseif self.dragType == 2 then - self.scrollBar.size = self.rectTransform.sizeDelta.x / (self.itemWidth * math.ceil(self.dataCount / self.fixedCount) + self.spacing.x) - end - if not oldIndex then - self.scrollBar.value = 0 - else - if self.dragType == 1 then - self.scrollBar.value = oldPos.y / self.itemDis - else - self.scrollBar.value = -oldPos.x / self.itemDis + -- 隐藏所有物体,并处理物体在数据结构中的位置 + for j=1, self.fixedCount do + for i=1, self.itemCount do + local item = self.cellItemList[j][i] + if item.go then + item.isActive = false + item.go:SetActive(false) end end + move(self.cellItemList[j], oldLine - self.dataLine) + end + + -- 刷新滑动条显示 + self:InitDragBar() + + -- 分帧加载物体 + local index, item, dataIndex + if self.co then + coroutine.stop(self.co) + end + self.co = coroutine.start(function() + -- 分帧加载期间不可拖动 + self.isCanDrag = false + + for i=1, self.itemCount do + for j=1, self.fixedCount do + item = self.cellItemList[j][i] + index = j+(i-1)*self.fixedCount + dataIndex = j+(i-1 + self.dataLine)*self.fixedCount + + if not item.go then + local go = newObject(self.item) + go.name = "item"..index + go.transform:SetParent(self.dragGO.transform) + go.transform.localScale = Vector3.one + go.transform.localPosition = Vector3.zero + go:SetActive(false) + + local tran = go:GetComponent("RectTransform") + tran.anchorMin = Vector2.New(0, 1) + tran.anchorMax = Vector2.New(0, 1) + + item.go = go + item.tran = tran + + end + + if item.go then + if self.dragType == 1 then + item.tran.anchoredPosition = Vector2.New(self.itemWidth * (j-1), (0.5-i - self.dataLine) * self.itemHeight) + else + item.tran.anchoredPosition = Vector2.New((i-0.5 + self.dataLine) * self.itemWidth, self.itemHeight * (1-j)) + end + self.goItemList[index] = item.go + end + SetUpdate(self, dataIndex, item) + coroutine.wait(0.03) + end + end + -- 加载完成可以拖动了 + self.isCanDrag = true + end) + + +end + +-- 初始化滑动条 +function this:InitDragBar() + if self.scrollBar then + -- 大小和位置 + if self.dragType == 1 then + self.scrollBar.size = self.rectTransform.sizeDelta.y / (self.itemHeight * math.ceil(self.dataCount / self.fixedCount) + self.spacing.y) + self.scrollBar.value = self.dragGOTran.anchoredPosition.y / self.itemDis + elseif self.dragType == 2 then + self.scrollBar.size = self.rectTransform.sizeDelta.x / (self.itemWidth * math.ceil(self.dataCount / self.fixedCount) + self.spacing.x) + self.scrollBar.value = -self.dragGOTran.anchoredPosition.x / self.itemDis + end + -- 滑动监听 self.scrollBar.onValueChanged:AddListener(function(f) + if not self.isCanDrag then return end local v2, curIndex if self.dragType == 1 then v2 = Vector2.Lerp(Vector2.zero, Vector2.New(0, self.itemDis), f) @@ -358,24 +444,13 @@ function this:SetData(dataList, updateFunc) v2 = Vector2.Lerp(Vector2.zero, Vector2.New(-self.itemDis, 0), f) curIndex = math.floor(-v2.x / self.itemWidth) end - self.dragGOTran.anchoredPosition = v2 SetItemIndex(self, curIndex) end) end - - if oldIndex then - if self.itemDis > 0 then - if self.dragType == 1 then - self.dragGOTran.anchoredPosition = Vector2.New(0, math.clamp(oldPos.y, 0, self.itemDis)) - elseif self.dragType == 2 then - self.dragGOTran.anchoredPosition = Vector2.New(math.clamp(oldPos.x, -self.itemDis, 0), 0) - end - end - SetItemIndex(self, oldIndex) - end end + function this:ForeachItemGO(func) if not func or not self.goItemList then return end for i=1, math.min(#self.goItemList, self.dataCount) do @@ -385,17 +460,22 @@ end --设置当前索引位置在最上层 function this:SetIndex(curIndex) - local itemOffset = math.ceil(curIndex / self.fixedCount) - 1 - if self.itemDis > 0 then - if self.dragType == 1 then - self.dragGOTran.anchoredPosition = Vector2.New(0, math.clamp(self.itemHeight * itemOffset, 0, self.itemDis)) - elseif self.dragType == 2 then - self.dragGOTran.anchoredPosition = Vector2.New(math.clamp(-self.itemWidth * itemOffset, -self.itemDis, 0), 0) - end - else - self.dragGOTran.anchoredPosition = Vector2.New(0, 0) - end - SetItemIndex(self, itemOffset) + Log("setIndex "..curIndex) + -- if self.co then + -- coroutine.stop(self.co) + -- end + -- local itemOffset = math.ceil(curIndex / self.fixedCount) - 1 + -- if self.itemDis > 0 then + -- if self.dragType == 1 then + -- self.dragGOTran.anchoredPosition = Vector2.New(0, math.clamp(self.itemHeight * itemOffset, 0, self.itemDis)) + -- elseif self.dragType == 2 then + -- self.dragGOTran.anchoredPosition = Vector2.New(math.clamp(-self.itemWidth * itemOffset, -self.itemDis, 0), 0) + -- end + -- else + -- self.dragGOTran.anchoredPosition = Vector2.New(0, 0) + -- end + -- SetItemIndex(self, itemOffset) + self:SetShow(curIndex) end --通过item预设获取关联的数据项索引