cocos-lua 制作无限循环ScrollView ,遇到的坑记录下来,笔记

孙化
2023-12-01

本来是在紧急开发中,想找官方已经有的,但是官方好像没有,无奈,只能自己写了。

    目前只写到了可以循环使用,也可以到顶不动,但是那个回弹效果还没写完。

    第一个坑:找监听。

        百度上面说是有几种办法,我都试了。第一感觉就是没用,然后不断的尝试找资料,后来发现是因为点击事件的原因,我ScrollView 的底图是一个layout,打开layout点击事件后就收不到全局点击事件了,所以需要关闭点击事件。

        self.image = ccui.Layout:create()
        self.image:ignoreContentAdaptWithSize(false)
        self.image:setName("Layout")
        self.image:setContentSize(self.startX * 2, self.scrollViewHeight)
        self.image:setPosition(self.x , self.y)
        self.image:setAnchorPoint(0.5,0.5)
        self.image:setOpacity(0)
        self.image:setClippingEnabled(true)

        self:addChild(self.image)     其他的监听都没返回touch坐标,所以不行

     第二个坑:额,暂时没啥坑。先不写。下面贴代码:

        



local M = class("ScrollView1" , cc.Node)
local Utils = require("Utils")


function M:ctor(par)
    if par then
          self.scrollView = par.scrollView
          self.gapY = par.gapY
          self.scrollViewHeight = par.scrollViewHeight
          self.startX = par.startX
          self.object = par.object
          self.x = par.x or 500
          self.y = par.y or 500
          if par.maxShowView then
             self.maxShowView = par.maxShowView
          else
             self.maxShowView = 10
          end
          self.isQidong = false
    end


    self.objectList = {}
    self.objectViewList = {}
    self.image = ccui.Layout:create()
    self.image:ignoreContentAdaptWithSize(false)
    self.image:setName("Layout")
    self.image:setContentSize(self.startX * 2, self.scrollViewHeight)
    self.image:setPosition(self.x , self.y)
    self.image:setAnchorPoint(0.5,0.5)
    self.image:setOpacity(0)
    self.image:setClippingEnabled(true)
    self:addChild(self.image)
    self:TouchEvent()
end


function M:ValueMoveUp()
    -- 当倒数第二个元素高于限制的高度时,便需要将第一个元素放到最后面
    local temp = self.objectList[self.maxShowView - 1]
    if temp:getPositionY() > self.y - self.scrollViewHeight/2 then
        if self.par[self.maxIndex + 1] then
            local maxPositionX = self.objectList[self.maxShowView]:getPositionX()
            local maxPositionY = self.objectList[self.maxShowView]:getPositionY() - self.gapY
            local tempValue = table.remove(self.objectList , 1)
            self.maxIndex = self.maxIndex + 1
            self.minIndex = self.minIndex + 1
            tempValue:setPosition(maxPositionX , maxPositionY)
            tempValue:Update(self.par[self.maxIndex])
            table.insert(self.objectList , tempValue)
        else
            local maxPositionX = self.objectList[self.maxShowView]:getPositionX()
            local maxPositionY = self.objectList[self.maxShowView]:getPositionY() - self.gapY
            local tempValue = table.remove(self.objectList , 1)
            self.maxIndex = 1
            self.minIndex = self.minIndex + 1
            tempValue:setPosition(maxPositionX , maxPositionY)
            tempValue:Update(self.par[self.maxIndex])
            table.insert(self.objectList , tempValue)
        end
    end 
end


function M:ValueMoveDown()
    -- 当第二个元素低于警戒值时,便将最后一个元素放到最前面
    local temp = self.objectList[2]
    if temp:getPositionY() < self.y + self.scrollViewHeight/2 then
        if self.par[self.minIndex - 1] then
            local minPositionX = self.objectList[1]:getPositionX()
            local minPositionY = self.objectList[1]:getPositionY() + self.gapY
            local tempValue = table.remove(self.objectList , self.maxShowView)
            self.maxIndex = self.maxIndex - 1
            self.minIndex = self.minIndex - 1
            tempValue:setPosition(minPositionX , minPositionY)
            tempValue:Update(self.par[self.minIndex])
            table.insert(self.objectList , 1 , tempValue)
        else
            local maxPositionX = self.objectList[1]:getPositionX()
            local maxPositionY = self.objectList[1]:getPositionY() - self.gapY
            local tempValue = table.remove(self.objectList , 1)
            self.minIndex = #self.par
            self.maxIndex = self.maxIndex - 1
            tempValue:setPosition(maxPositionX , maxPositionY)
            tempValue:Update(self.par[self.minIndex])
            table.insert(self.objectList, 1 , tempValue)
        end
    end 
end


function M:TouchEvent()
    local x = 0;
    local y = 0;
    local function onMyTouchBegan(touch,event)
        local pos = touch:getLocation()
        x = pos.x
        y = pos.y
        if cc.rectContainsPoint(self.image:getBoundingBox(), self.image:getParent():convertToNodeSpace(cc.p(x, y))) then
            return true
        end
        return false
    end


    local function onTouchMove(touch,event)
        local pos = touch:getLocation()
        local rex = pos.x - x
        local rey = pos.y - y
        x = pos.x
        y = pos.y


        if rey > 0 then
            print("向上移动")
            -- 判断向上移动,最下面的元素到没到底点
            if self.objectList[#self.objectList] and self.objectList[#self.objectList]:getPositionY() >= (self.y - self.scrollViewHeight/2) and self.maxIndex == #self.par then
                return true
            end
            if self.isQidong then
                self:ValueMoveUp()
            else
                
            end
        elseif rey < 0 then
            print("向下移动")
            -- 判断向下移动,最上面的元素到没到顶点  
            if self.objectList[1]:getPositionY() <= (self.y + self.scrollViewHeight/2 - self.gapY) and self.minIndex == 1 then
                return true
            end          
            if self.isQidong then
                self:ValueMoveDown()
            else
                
            end
        end


        for index,value in pairs(self.objectList) do
            value:setPosition(value:getPositionX() , value:getPositionY() + rey)
        end
        return true
    end


    local function onMyTouchEnded(touch,event)
        
    end


    local touchListen = cc.EventListenerTouchOneByOne:create()
    touchListen:setSwallowTouches(false)
    touchListen:registerScriptHandler(onMyTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN)
    touchListen:registerScriptHandler(onMyTouchEnded,cc.Handler.EVENT_TOUCH_ENDED)
    touchListen:registerScriptHandler(onTouchMove,cc.Handler.EVENT_TOUCH_MOVED)
    
    local eventDispatcher = cc.Director:getInstance():getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(touchListen , self.image)
end


-- 获取一个对象
function M:ObtinObject(type)
    -- 遍历找下是否有空闲的对象
    for index,value in ipairs(self.objectViewList) do
        if value:getTag() == 0 then
            value:setTag(1)
            return value
        end
    end
    -- 没有空闲的对象,则生成一个空闲的对象
    local object
    if type then
        object = self.object:create(type)
    else
        object = self.object:create()
    end
    object:setTag(1)
    table.insert(self.objectViewList , object)
    return object
end


-- 删除一个对象
function M:RemoveObject(value)
    if type(value) == "number" then
        self.objectViewList[value]:setTag(0)
        self.objectViewList[value]:setPosition(-display.width , -display.height)
    elseif type(value) == "userData" then
        value:setTag(0)
        value:setPosition(-display.width , -display.height)
    end
end


function M:Update(par,type)
    self.par = par
    local parLength = Utils.GetTableLength(par)
    self.startY = self.scrollViewHeight - self.gapY/2 
    if parLength > self.maxShowView and self.maxShowView > #self.objectList then
        local objectListLength = #self.objectList
        self.isQidong = true
        self.minIndex = 1
        self.maxIndex = self.maxShowView
        for index = objectListLength + 1, self.maxShowView do
            local value = self:ObtinObject(type)
            value:Update(self.par[index])
            value:setPosition(self.startX , self.startY - self.gapY * (index - 1))
            if value.OnOpen then
                value:OnOpen()
            end
            if type then
                value:SwitchState(type)
            end
            table.insert(self.objectList, value)
            self.image:addChild(value)
        end
    elseif parLength <= self.maxShowView then
        self.isQidong = false
        self.minIndex = 1
        self.maxIndex = parLength
        -- 如果需要显示的个数大于当前的元素个数,则生成几个元素个数
        local objectListLength = #self.objectList 
        if parLength > objectListLength then
            for index = objectListLength + 1 ,parLength do
                local value = self:ObtinObject(type)
                if value.OnOpen then
                    value:OnOpen()
                end
                self.image:addChild(value)
                table.insert(self.objectList, value)
            end
        -- 如果需要显示的个数小于当前的元素个数,则删掉几个元素个数,但是保留缓存
        elseif parLength < objectListLength then
            for index = parLength , objectListLength + 1 , -1 do
                self.image:removeChild(self.objectList[index] , false)
                self:RemoveObject(self.objectList[index])
                table.remove(self.objectList , index)
            end
        end


        for i in ipairs(self.par) do
            self.objectList[i]:Update(self.par[i])
            self.objectList[i]:setPosition(self.startX , self.startY - self.gapY * (i - 1))
            if type then
                self.objectList[i]:SwitchState(type)
            end
        end
    end
end


function M:OnOpen()
    for index , value in ipairs(self.objectList) do
        value:OnOpen()
    end
end


function M:OnClose()
    for index , value in ipairs(self.objectList) do
        value:OnClose()
    end
end


return M


 类似资料: