|
|
-
- LoopScrowViewMgr = LoopScrowViewMgr or BaseClass()
-
- local LoopScrowViewMgr = LoopScrowViewMgr
-
- function LoopScrowViewMgr:__init()
- self.item_width = 100 --item 宽度
- self.item_height = 100 --item 高度
-
- self.cull_content = true --是否隐藏 滑动列表之外的物体
-
- self.min_index = 0
- self.max_index = 0
-
- self.onInitializeItem = nil --更新item的委托
-
- self.max_per_line = 1 --每一行有多少列
-
- self.mTrans = nil --当前挂载这个组件的物体
-
- self.mPanel = nil -- scrowView 物体
-
- self.mScroll = nil -- scrowView 组件
-
- self.mHorizontal = false --是否是水平
-
- self.force_reset = true --强制复位
-
- self.item_list = {}
-
- self.mCachedScrowView = false
-
- self.mOriginalPosition = Vector3.zero
-
- self.mNeedToWrap = false
-
- self.mPanelDelta = Vector2.zero
-
- self.show_count = 0
-
- self.item_num = 0
-
- self.offset = 0
-
- self.start_pos = {x=0, y=0}
-
- self.corners = {}
-
- self.wrap_content_cb = false
- end
-
- function LoopScrowViewMgr:Init(mPanel,mTrans,max_per_line,item_width,item_height,onInitializeItem,offset, offset_y, start_pos, wrap_content_cb)
- self.mPanel = mPanel
- if self.mPanel.transform.pivot.x ~= 0.5 or self.mPanel.transform.pivot.y ~= 0.5 then
- -- 不要搞事情,计算的时候锚点不对会有计算错误请在预制就设置好scrollView的锚点
- -- self.mPanel.transform.pivot = Vector2(0.5,0.5)
- local size = self.mPanel.rect.size
- local mPanel_x = GetLocalPositionX(self.mPanel.transform)
- local mPanel_y = GetLocalPositionY(self.mPanel.transform)
- if self.mPanel.transform.pivot.x == 0 and self.mPanel.transform.pivot.y == 1 then
- self.mPanel.transform.localPosition = Vector3(mPanel_x + size.x/2, mPanel_y - size.y/2, 0)
- elseif self.mPanel.transform.pivot.x == 1 and self.mPanel.transform.pivot.y == 0 then
- self.mPanel.transform.localPosition = Vector3(mPanel_x - size.x/2, mPanel_y + size.y/2, 0)
- end
- self.mPanel.transform.pivot = Vector2(0.5,0.5)
- end
-
- self.mTrans = mTrans
- self.item_width = item_width
- self.item_height = item_height
- self.max_per_line = max_per_line or 1
- self.onInitializeItem = onInitializeItem
- self.offset = offset or 0
- self.start_pos = start_pos or {x=0, y=0}
- self.wrap_content_cb = wrap_content_cb or false
- self:CachedScrowView()
- end
-
- function LoopScrowViewMgr:__delete()
- if self.mScroll then
- self.mScroll.onValueChanged:RemoveAllListeners()
- end
-
- self.item_list = {}
-
- self.onInitializeItem = nil --更新item的委托
- self.mTrans = nil --当前挂载这个组件的物体
- self.mPanel = nil -- scrowView 物体
- self.mScroll = nil -- scrowView 组件
- end
-
- function LoopScrowViewMgr:ClearItemList()
- if self.item_list then
- for i,v in ipairs(self.item_list) do
- v:SetVisible(false, true)
- end
- self.max_index = 0
- end
- end
-
-
- function LoopScrowViewMgr:SetContentSizeData()
-
- if self.mHorizontal then
- if self.mTrans then
- self.mTrans.sizeDelta = Vector2(math.ceil(self.show_count/self.max_per_line) * self.item_width,self.max_per_line * self.item_height)
- end
- else
- if self.mTrans then
- self.mTrans.sizeDelta = Vector2(self.max_per_line * self.item_width,math.ceil(self.show_count/self.max_per_line) * self.item_height)
- end
- end
- end
-
- function LoopScrowViewMgr:CachedScrowView()
- if self.mCachedScrowView then
- if self.mScroll == nil then
- return
- end
- return self.mScroll and self.mScroll.horizontal or self.mScroll.vertical
- end
-
- self.mCachedScrowView = true
-
- if self.mPanel == nil then return false end
- if self.mTrans == nil then return false end
-
- self.mPanelDelta = self.mPanel.rect.size
-
- self.mOriginalPosition = self.mTrans.localPosition
- self.mScroll = self.mPanel.gameObject:GetComponent("ScrollRect")
-
- if self.mScroll == nil then return false end
-
- if self.mScroll.horizontal then
- self.mHorizontal = true
- elseif self.mScroll.vertical then
- self.mHorizontal = false
- else
- return false
- end
-
- return true
- end
-
- function LoopScrowViewMgr:InitChildren(item_list,show_count)
- self.show_count = show_count
- if not self:CachedScrowView() then
- return
- end
-
- if item_list then
- local len = TableSize(item_list)
- self.min_index = 1
- self.max_index = show_count
- self.mNeedToWrap = show_count > len
- self.item_list = {}
-
- if show_count < 0 or show_count > len then
- show_count = len
- end
-
- local item
- for i = 1,len do
- item = item_list[i]
- if show_count > 0 and item then
- item:SetVisible(true, true)
- table.insert(self.item_list,item)
- show_count = show_count - 1
- elseif item then
- table.insert(self.item_list,item)
- item:SetVisible(false, true)
- end
- end
- --是真实的item个数
- self.item_num = #self.item_list
- else
- self.item_num = 0
- end
- end
-
- function LoopScrowViewMgr:ResetScrowViewPanel(is_not_reset_pos)
- local is_not_reset_pos = is_not_reset_pos
- if self.mScroll then
- self.mScroll.onValueChanged:RemoveAllListeners()
- self:ResetPosition(is_not_reset_pos)
- self.mScroll.onValueChanged:AddListener(function()
- self:WrapContent()
- end)
- end
- end
-
- function LoopScrowViewMgr:ResetPosition(is_not_reset_pos)
- if not is_not_reset_pos then
- self.mTrans.localPosition = self.mOriginalPosition
- end
- end
-
- function LoopScrowViewMgr:ResetItemListPosition()
- local len = self.item_num
- for i = 1,len do
- local item = self.item_list[i]
- -- item:SetGameObjectName(tostring(i))
-
- if self.mHorizontal then
- local pos = self.max_per_line > 0 and
- Vector3(math.floor((i - 1) / self.max_per_line) * self.item_width + self.offset,- (math.floor(i - 1) % self.max_per_line * self.item_height), 0) or
- Vector3(-(i-1) * self.item_width,0,0)
- item:SetPosition(pos.x +self.start_pos.x, pos.y + self.start_pos.y)
- else
- local pos = self.max_per_line > 0 and
- Vector3(math.floor(i - 1) % self.max_per_line * self.item_width ,- math.floor((i - 1) / self.max_per_line) * self.item_height,0) or
- Vector3(0,-(i-1) * self.item_height,0)
- item:SetPosition(pos.x +self.start_pos.x, pos.y + self.start_pos.y)
- end
- end
- end
-
- function LoopScrowViewMgr:RestToBeginning(is_not_reset_pos)--is_not_reset_pos为true则不重置scroll位置
-
- if not self:CachedScrowView() then
- return
- end
-
- self:ResetScrowViewPanel(is_not_reset_pos)
- self:ResetItemListPosition()
- self.force_reset = true
- self:WrapContent()
- self.force_reset = false
- end
-
- --强制更新所有item数据
- function LoopScrowViewMgr:ForceUpdateCurrentItems()
- -- self.force_reset = true
- -- self:WrapContent()
- -- self.force_reset = false
- if self.mNeedToWrap and self.mTrans then
- self.corners = self:GetWorldCorners()
- for i = 1,4 do
- local v = self.corners[i]
- v = self.mTrans:InverseTransformPoint(v)
- self.corners[i] = v
- end
- end
- self:ForceUpdatePos(self.corners)
- end
-
- function LoopScrowViewMgr:ForceUpdatePos(corners)
- if corners == nil or #corners < 1 then return end
- if self.mHorizontal then
- local extents = self.max_per_line > 0 and (self.item_width * math.floor(self.item_num / self.max_per_line)) or self.item_width * self.item_num
- local halfExtents = extents*0.5
- local center = (corners[1] + corners[3]) * 0.5
- for i = 1,self.item_num do
- local item = self.item_list[i]
- local distance = item:GetPosition().x + self.item_width/2 - center.x
- local realIndex = self:GetRealIndex(item:GetPosition())
- if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
- -- item:SetGameObjectName(tostring(realIndex))
- if self.max_index > #self.item_list then
- item:SetVisible(true, true)
- end
- self:UpdateItem(item,i,realIndex)
- else
- item:SetVisible(false, true)
- end
- if extents > self.mPanelDelta.x then
- if math.abs(distance) > halfExtents then
- local pos = DeepCopy(item:GetPosition())
- pos.x = distance < 0 and pos.x + extents or pos.x - extents
- local realIndex = self:GetRealIndex(pos)
- if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
- item:SetPosition(pos.x, pos.y)
- -- item:SetGameObjectName(tostring(realIndex))
- if self.max_index > #self.item_list then
- item:SetVisible(true, true)
- end
- self:UpdateItem(item,i,realIndex)
- end
- end
- end
- end
- else
- local extents = self.max_per_line > 0 and (self.item_height * math.floor(self.item_num / self.max_per_line)) or self.item_height * self.item_num
- local halfExtents = extents*0.5
- local center = (corners[1] + corners[3]) * 0.5
- for i = 1,self.item_num do
- local item = self.item_list[i]
- local distance = item:GetPosition().y - self.item_height/2 - center.y
- local realIndex = self:GetRealIndex(item:GetPosition())
- if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
- -- item:SetGameObjectName(tostring(realIndex))
- if self.max_index > #self.item_list then
- item:SetVisible(true, true)
- end
- self:UpdateItem(item,i,realIndex)
- else
- item:SetVisible(false, true)
- end
- if extents > self.mPanelDelta.y then
- if math.abs(distance) > halfExtents then
- local pos = DeepCopy(item:GetPosition())
- pos.y = distance < 0 and pos.y + extents or pos.y - extents
- local realIndex = self:GetRealIndex(pos)
- if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
- item:SetPosition(pos.x, pos.y)
- -- item:SetGameObjectName(tostring(realIndex))
- if self.max_index > #self.item_list then
- item:SetVisible(true, true)
- end
- self:UpdateItem(item,i,realIndex)
- end
- end
- end
- end
- end
- end
-
- function LoopScrowViewMgr:GetWorldCorners()
-
- local mCorners = {}
-
- local x0 = -0.5 * self.mPanelDelta.x
- local y0 = -0.5 * self.mPanelDelta.y
- local x1 = x0 + self.mPanelDelta.x
- local y1 = y0 + self.mPanelDelta.y
-
- mCorners[1] = self.mPanel:TransformPoint(x0,y0,0)
- mCorners[2] = self.mPanel:TransformPoint(x0,y1,0)
- mCorners[3] = self.mPanel:TransformPoint(x1,y1,0)
- mCorners[4] = self.mPanel:TransformPoint(x1,y0,0)
-
- return mCorners
-
- end
-
- function LoopScrowViewMgr:WrapContent()
-
- if not self:CachedScrowView() then
- return
- end
-
- if self.mNeedToWrap or self.force_reset then
- self.corners = self:GetWorldCorners()
- for i = 1,4 do
- local v = self.corners[i]
- v = self.mTrans:InverseTransformPoint(v)
- self.corners[i] = v
- end
- if self.mHorizontal then
- self:WrapHorizontal(self.corners)
- else
- self:WrapVertical(self.corners)
- end
- end
-
- if self.wrap_content_cb then
- self.wrap_content_cb()
- end
- end
-
- function LoopScrowViewMgr:GetRealIndex(pos)
- if self.mHorizontal then
- return self.max_per_line > 0 and
- --这里一定要四舍五入,因为 位置会出现 原本 是 440,unity 可能会变成439.333
- round((pos.x - self.offset) / self.item_width) * self.max_per_line + round(-pos.y / self.item_height) + 1 or
- round(pos.x / self.item_width)
- else
- return self.max_per_line > 0 and
- --这里一定要四舍五入,因为 位置会出现 原本 是 440,unity 可能会变成439.333
- round(- pos.y / self.item_height) * self.max_per_line + round(pos.x / self.item_width) + 1 or
- round(- pos.y / self.item_height)
- end
- end
-
- function LoopScrowViewMgr:WrapVertical(corners)
- local extents = self.max_per_line > 1 and (self.item_height * math.floor(self.item_num / self.max_per_line)) or self.item_height * self.item_num
-
- local halfExtents = extents*0.5
- local center = (corners[1] + corners[3]) * 0.5
- for i = 1,self.item_num do
- local item = self.item_list[i]
-
- local distance = item:GetPosition().y - self.item_height/2 - center.y
- if self.force_reset then
- local realIndex = self:GetRealIndex(item:GetPosition())
- if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
- -- item:SetGameObjectName(tostring(realIndex))
- if self.max_index > #self.item_list then
- item:SetVisible(true, true)
- end
- self:UpdateItem(item,i,realIndex)
- end
- elseif extents > self.mPanelDelta.y then
- if math.abs(distance) > halfExtents then
- local pos = DeepCopy(item:GetPosition())
- pos.y = distance < 0 and pos.y + extents or pos.y - extents
- local realIndex = self:GetRealIndex(pos)
- if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
- item:SetPosition(pos.x, pos.y)
- -- item:SetGameObjectName(tostring(realIndex))
- if self.max_index > #self.item_list then
- item:SetVisible(true, true)
- end
- self:UpdateItem(item,i,realIndex)
- end
- end
- end
- end
- end
-
- function LoopScrowViewMgr:WrapHorizontal(corners)
- local extents = self.max_per_line > 0 and (self.item_width * math.floor(self.item_num / self.max_per_line)) or self.item_width * self.item_num
-
- local halfExtents = extents*0.5
- local center = (corners[1] + corners[3]) * 0.5
- for i = 1,self.item_num do
- local item = self.item_list[i]
-
- local distance = item:GetPosition().x + self.item_width/2 - center.x
- if self.force_reset then
- local realIndex = self:GetRealIndex(item:GetPosition())
- if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
- -- item:SetGameObjectName(tostring(realIndex))
- if self.max_index > #self.item_list then
- item:SetVisible(true, true)
- end
- self:UpdateItem(item,i,realIndex)
- end
- elseif extents > self.mPanelDelta.x then
- if math.abs(distance) > halfExtents then
- local pos = DeepCopy(item:GetPosition())
- pos.x = distance < 0 and pos.x + extents or pos.x - extents
- local realIndex = self:GetRealIndex(pos)
- if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
- item:SetPosition(pos.x, pos.y)
- -- item:SetGameObjectName(tostring(realIndex))
- if self.max_index > #self.item_list then
- item:SetVisible(true, true)
- end
- self:UpdateItem(item,i,realIndex)
- end
- end
- end
- end
- end
-
- function LoopScrowViewMgr:UpdateItem(item,index,realIndex)
- if self.onInitializeItem then
- self.onInitializeItem(item,index,realIndex)
- end
- end
-
- function LoopScrowViewMgr:CenterOnChild(index)
- local floor = math.floor
- if self.mHorizontal then
- local view_num = floor(self.mPanelDelta.x/self.item_width)
- local endPoint = self.mTrans.sizeDelta.x - self.item_width
- local offset = (index - math.ceil(view_num/2)) * self.item_width
- for i = 1,self.item_num do
- local item = self.item_list[i]
- local pos = item:GetPosition()
- pos.x = (i-1)*self.item_width + offset
- pos.x = pos.x <= endPoint and pos.x or (offset - (i-1)*self.item_width)
- item:SetPosition(pos.x, pos.y)
- local realIndex = self:GetRealIndex(pos)
- self:UpdateItem(item,i,realIndex)
- end
- local content_pos = self.mTrans.anchoredPosition
- content_pos.x = content_pos.x - offset
- self.mTrans.anchoredPosition = content_pos
- else
-
- end
-
- end
-
- --跳转到实际索引所在的位置
- function LoopScrowViewMgr:JumpToChild(index)
- if index and index > 0 then
- print("==== jump to index:", index)
- if self.mHorizontal then
- if self.show_count * self.item_width > self.mPanel.sizeDelta.x then
- local max_index = math.min(self.max_index, self.item_num)
- local tran_posX = -(index - 1)*self.item_width
- if tran_posX < -(self.show_count * self.item_width - self.mPanel.sizeDelta.x) then
- tran_posX = -(self.show_count * self.item_width - self.mPanel.sizeDelta.x)
- end
- self.mTrans.localPosition = Vector2(tran_posX, self.mTrans.localPosition.y)
- local op_index = 1
- for i = 1, max_index do
- local item = self.item_list[i]
- local pos = item:GetPosition()
- pos.x = (i + index - 2)*self.item_width - self.offset
- if pos.x >= (self.show_count * self.item_width) then
- op_index = op_index + 1
- pos.x = -(op_index - index)*self.item_width - self.offset
- end
- item:SetPosition(pos.x + self.start_pos.x, pos.y + self.start_pos.y)
- local realIndex = self:GetRealIndex(pos)
- -- item:SetGameObjectName(tostring(realIndex))
- self:UpdateItem(item,i,realIndex)
- end
- end
- else
- if self.show_count * self.item_height > self.mPanel.sizeDelta.y then
- local max_index = math.min(self.max_index, self.item_num)
- local tran_posY = (index - 1)*self.item_height
- if tran_posY > (self.show_count * self.item_height - self.mPanel.sizeDelta.y) then
- tran_posY = self.show_count * self.item_height - self.mPanel.sizeDelta.y
- end
- self.mTrans.localPosition = Vector2(self.mTrans.localPosition.x, tran_posY)
- local op_index = 1
- for i = 1, max_index do
- local item = self.item_list[i]
- local pos = item:GetPosition()
- pos.y = -(math.ceil(i/self.max_per_line) + index - 2)*self.item_height
- if pos.y <= -(self.show_count * self.item_height) then
- op_index = op_index + 1
- pos.y = (op_index - index)*self.item_height
- end
- item:SetPosition(pos.x + self.start_pos.x, pos.y + self.start_pos.y)
- local realIndex = self:GetRealIndex(pos)
- self:UpdateItem(item,i,realIndex)
- end
- end
- end
- end
- end
-
- --获取展示在显示窗口的item
- function LoopScrowViewMgr:GetShowInViewportItem()
- local mPos = self.mTrans.localPosition
- local show_key_list = {}
- for k,v in pairs(self.item_list) do
- local bool_visible = v:GetVisible()
- if bool_visible then
- local pos = v:GetPosition()
- if (mPos.y+pos.y) <= self.item_height/2 and (mPos.y+pos.y) >= -self.mPanelDelta.y
- and (mPos.x+pos.x) >= -self.item_width/2 and (mPos.x+pos.x) <= self.mPanelDelta.x then
- table.insert(show_key_list, k)
- end
- end
- end
- return show_key_list
- end
|