• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Quick-lua3.3之listview

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

  listview列表,在游戏中非常常见,比如道具列表,玩家列表,排行榜等等。每个版本可能使用方法可能有些差别,但是大同小异,原理和用途都是那几种,设置方向,间隔等。

这里是quick-lua3.3版本的使用和简单介绍.

UIListView 继承自 UIScrollView ,掌握 UIScrollView 用法和源码是非常有必要滴

使用及几个用法

初始化listView

1.例子

self.listView = cc.ui.UIListView.new({
       direction = cc.ui.UIScrollView.DIRECTION_VERTICAL,
       alignment = cc.ui.UIListView.ALIGNMENT_VCENTER,
       viewRect = cc.rect(0,0,bg:getContentSize().width - 28, bg:getContentSize().height-88),
   })

2.参数

-   direction 列表控件的滚动方向,默认为垂直方向
-   alignment listViewItem中content的对齐方式,默认为垂直居中
-   viewRect 列表控件的显示区域
-   scrollbarImgH 水平方向的滚动条
-   scrollbarImgV 垂直方向的滚动条
-   bgColor 背景色,nil表示无背景色
-   bgStartColor 渐变背景开始色,nil表示无背景色
-   bgEndColor 渐变背景结束色,nil表示无背景色
-   bg 背景图
-   bgScale9 背景图是否可缩放
-    capInsets 缩放区域
(1)direction
UIScrollView.DIRECTION_BOTH              = 0
UIScrollView.DIRECTION_VERTICAL          = 1  --垂直
UIScrollView.DIRECTION_HORIZONTAL        = 2
(2)alignment 
UIListView.ALIGNMENT_LEFT            = 0
UIListView.ALIGNMENT_RIGHT            = 1
UIListView.ALIGNMENT_VCENTER        = 2
UIListView.ALIGNMENT_TOP            = 3
UIListView.ALIGNMENT_BOTTOM            = 4
UIListView.ALIGNMENT_HCENTER        = 5
 

item 、设置间隔:

1.使用:

local margin = {top = 0,bottom = 5,left = 0,right = 0}

local listItem = self.listView:newItem(node)
listItem:setMargin(margin) --设置间隔 (如果是玩家自己的话,就放大一点)
listItem:setItemSize(node:getContentSize().width, node:getContentSize().height)

setMargin原理

2.在设置itemsize时处理margin_

function UIListViewItem:setItemSize(w, h, bNoMargin)
    if not bNoMargin then
        if UIScrollView.DIRECTION_VERTICAL == self.lvDirection_ then
            h = h + self.margin_.top + self.margin_.bottom
        else
            w = w + self.margin_.left + self.margin_.right
        end
    end

    -- print("UIListViewItem - setItemSize w:" .. w .. " h:" .. h)

    local oldSize = {width = self.width, height = self.height}
    local newSize = {width = w, height = h}

    self.width = w or 0
    self.height = h or 0
    self:setContentSize(w, h)

    local bg = self:getChildByTag(UIListViewItem.BG_TAG)
    if bg then
        bg:setContentSize(w, h)
        bg:setPosition(cc.p(w/2, h/2))
    end

    self.listener(self, newSize, oldSize)
end

 注:设置间隔可以直接

listItem:setItemSize(node:getContentSize().width, node:getContentSize().height + XXXXX)
直接加也可以

UIListView.lua函数

framework/cc/ui/文件夹下

--------------------------------
-- @module UIListView

--[[--

  quick 列表控件

]]

local UIScrollView = import(".UIScrollView")
local UIListView = class("UIListView", UIScrollView)

local UIListViewItem = import(".UIListViewItem")


UIListView.DELEGATE                    = "ListView_delegate"
UIListView.TOUCH_DELEGATE            = "ListView_Touch_delegate"

UIListView.CELL_TAG                    = "Cell"
UIListView.CELL_SIZE_TAG            = "CellSize"
UIListView.COUNT_TAG                = "Count"
UIListView.CLICKED_TAG                = "Clicked"
UIListView.UNLOAD_CELL_TAG            = "UnloadCell"

UIListView.BG_ZORDER                 = -1
UIListView.CONTENT_ZORDER            = 10

UIListView.ALIGNMENT_LEFT            = 0
UIListView.ALIGNMENT_RIGHT            = 1
UIListView.ALIGNMENT_VCENTER        = 2
UIListView.ALIGNMENT_TOP            = 3
UIListView.ALIGNMENT_BOTTOM            = 4
UIListView.ALIGNMENT_HCENTER        = 5

-- start --

--------------------------------
-- UIListView构建函数
-- @function [parent=#UIListView] new
-- @param table params 参数表

--[[--

UIListView构建函数

可用参数有:

-   direction 列表控件的滚动方向,默认为垂直方向
-   alignment listViewItem中content的对齐方式,默认为垂直居中
-   viewRect 列表控件的显示区域
-   scrollbarImgH 水平方向的滚动条
-   scrollbarImgV 垂直方向的滚动条
-   bgColor 背景色,nil表示无背景色
-   bgStartColor 渐变背景开始色,nil表示无背景色
-   bgEndColor 渐变背景结束色,nil表示无背景色
-   bg 背景图
-   bgScale9 背景图是否可缩放
-    capInsets 缩放区域

]]
-- end --

function UIListView:ctor(params)
    UIListView.super.ctor(self, params)

    self.items_ = {}
    self.direction = params.direction or UIScrollView.DIRECTION_VERTICAL
    self.alignment = params.alignment or UIListView.ALIGNMENT_VCENTER
    self.bAsyncLoad = params.async or false
    self.container = cc.Node:create()
    -- self.padding_ = params.padding or {left = 0, right = 0, top = 0, bottom = 0}

    -- params.viewRect.x = params.viewRect.x + self.padding_.left
    -- params.viewRect.y = params.viewRect.y + self.padding_.bottom
    -- params.viewRect.width = params.viewRect.width - self.padding_.left - self.padding_.right
    -- params.viewRect.height = params.viewRect.height - self.padding_.bottom - self.padding_.top

    self:setDirection(params.direction)
    self:setViewRect(params.viewRect)
    self:addScrollNode(self.container)
    self:onScroll(handler(self, self.scrollListener))

    self.size = {}
    self.itemsFree_ = {}
    self.delegate_ = {}
    self.redundancyViewVal = 0 --异步的视图两个方向上的冗余大小,横向代表宽,竖向代表高
end

function UIListView:onCleanup()
    self:releaseAllFreeItems_()
end

-- start --

--------------------------------
-- 列表控件触摸注册函数
-- @function [parent=#UIListView] onTouch
-- @param function listener 触摸临听函数
-- @return UIListView#UIListView  self 自身

-- end --

function UIListView:onTouch(listener)
    self.touchListener_ = listener

    return self
end

-- start --

--------------------------------
-- 列表控件设置所有listItem中content的对齐方式
-- @function [parent=#UIListView] setAlignment
-- @param number align 对
-- @return UIListView#UIListView  self 自身

-- end --

function UIListView:setAlignment(align)
    self.alignment = align
end

-- start --

--------------------------------
-- 创建一个新的listViewItem项
-- @function [parent=#UIListView] newItem
-- @param node item 要放到listViewItem中的内容content
-- @return UIListViewItem#UIListViewItem 

-- end --

function UIListView:newItem(item)
    item = UIListViewItem.new(item)
    item:setDirction(self.direction)
    item:onSizeChange(handler(self, self.itemSizeChangeListener))

    return item
end

-- start --

--------------------------------
-- 设置显示区域
-- @function [parent=#UIListView] setViewRect
-- @return UIListView#UIListView  self

-- end --

function UIListView:setViewRect(viewRect)
    if UIScrollView.DIRECTION_VERTICAL == self.direction then
        self.redundancyViewVal = viewRect.height
    else
        self.redundancyViewVal = viewRect.width
    end

    UIListView.super.setViewRect(self, viewRect)
end

function UIListView:itemSizeChangeListener(listItem, newSize, oldSize)
    local pos = self:getItemPos(listItem)
    if not pos then
        return
    end

    local itemW, itemH = newSize.width - oldSize.width, newSize.height - oldSize.height
    if UIScrollView.DIRECTION_VERTICAL == self.direction then
        itemW = 0
    else
        itemH = 0
    end

    local content = listItem:getContent()
    transition.moveBy(content,
                {x = itemW/2, y = itemH/2, time = 0.2})

    self.size.width = self.size.width + itemW
    self.size.height = self.size.height + itemH
    if UIScrollView.DIRECTION_VERTICAL == self.direction then
        transition.moveBy(self.container,
            {x = -itemW, y = -itemH, time = 0.2})
        self:moveItems(1, pos - 1, itemW, itemH, true)
    else
        self:moveItems(pos + 1, table.nums(self.items_), itemW, itemH, true)
    end
end

function UIListView:scrollListener(event)
    if "clicked" == event.name then
        local nodePoint = self.container:convertToNodeSpace(cc.p(event.x, event.y))
        local pos
        local idx

        if self.bAsyncLoad then
            local itemRect
            for i,v in ipairs(self.items_) do
                local posX, posY = v:getPosition()
                local itemW, itemH = v:getItemSize()
                itemRect = cc.rect(posX, posY, itemW, itemH)
                if cc.rectContainsPoint(itemRect, nodePoint) then
                    idx = v.idx_
                    pos = i
                    break
                end
            end
        else
            nodePoint.x = nodePoint.x - self.viewRect_.x
            nodePoint.y = nodePoint.y - self.viewRect_.y

            local width, height = 0, self.size.height
            local itemW, itemH = 0, 0

            if UIScrollView.DIRECTION_VERTICAL == self.direction then
                for i,v in ipairs(self.items_) do
                    itemW, itemH = v:getItemSize()

                    if nodePoint.y < height and nodePoint.y > height - itemH then
                        pos = i
                        idx = pos
                        nodePoint.y = nodePoint.y - (height - itemH)
                        break
                    end
                    height = height - itemH
                end
            else
                for i,v in ipairs(self.items_) do
                    itemW, itemH = v:getItemSize()

                    if nodePoint.x > width and nodePoint.x < width + itemW then
                        pos = i
                        idx = pos
                        break
                    end
                    width = width + itemW
                end
            end
        end

        self:notifyListener_{name = "clicked",
            listView = self, itemPos = idx, item = self.items_[pos],
            point = nodePoint}
    else
        event.scrollView = nil
        event.listView = self
        self:notifyListener_(event)
    end

end

-- start --

--------------------------------
-- 在列表项中添加一项
-- @function [parent=#UIListView] addItem
-- @param node listItem 要添加的项
-- @param integer pos 要添加的位置,默认添加到最后
-- @return UIListView#UIListView 

-- end --

function UIListView:addItem(listItem, pos)
    self:modifyItemSizeIf_(listItem)

    if pos then
        table.insert(self.items_, pos, listItem)
    else
        table.insert(self.items_, listItem)
    end
    self.container:addChild(listItem)

    return self
end

-- start --

--------------------------------
-- 在列表项中移除一项
-- @function [parent=#UIListView] removeItem
-- @param node listItem 要移除的项
-- @param boolean bAni 是否要显示移除动画
-- @return UIListView#UIListView 

-- end --

function UIListView:removeItem(listItem, bAni)
    assert(not self.bAsyncLoad, "UIListView:removeItem() - syncload not support remove")

    local itemW, itemH = listItem:getItemSize()
    self.container:removeChild(listItem)

    local pos = self:getItemPos(listItem)
    if pos then
        table.remove(self.items_, pos)
    end

    if UIScrollView.DIRECTION_VERTICAL == self.direction then
        itemW = 0
    else
        itemH = 0
    end

    self.size.width = self.size.width - itemW
    self.size.height = self.size.height - itemH

    if 0 == table.nums(self.items_) then
        return
    end
    if UIScrollView.DIRECTION_VERTICAL == self.direction then
        self:moveItems(1, pos - 1, -itemW, -itemH, bAni)
    else
        self:moveItems(pos, table.nums(self.items_), -itemW, -itemH, bAni)
    end

    return self
end

-- start --

--------------------------------
-- 移除所有的项
-- @function [parent=#UIListView] removeAllItems
-- @return integer#integer 

-- end --

function UIListView:removeAllItems()
    self.container:removeAllChildren()
    self.items_ = {}

    return self
end

-- start --

--------------------------------
-- 取某项在列表控件中的位置
-- @function [parent=#UIListView] getItemPos
-- @param node listItem 列表项
-- @return integer#integer 

-- end --

function UIListView:getItemPos(listItem)
    for i,v in ipairs(self.items_) do
        if v == listItem then
            return i
        end
    end
end

-- start --

--------------------------------
-- 判断某项是否在列表控件的显示区域中
-- @function [parent=#UIListView] isItemInViewRect
-- @param integer pos 列表项位置
-- @return boolean#boolean 

-- end --

function UIListView:isItemInViewRect(pos)
    local item
    if "number" == type(pos) then
        item = self.items_[pos]
    elseif "userdata" == type(pos) then
        item = pos
    end

    if not item then
        return
    end
    
    local bound = item:getBoundingBox()
    local nodePoint = self.container:convertToWorldSpace(
        cc.p(bound.x, bound.y))
    bound.x = nodePoint.x
    bound.y = nodePoint.y

    return cc.rectIntersectsRect(self.viewRect_, bound)
end

-- start --

--------------------------------
-- 加载列表
-- @function [parent=#UIListView] reload
-- @return UIListView#UIListView 

-- end --

function UIListView:reload()
    if self.bAsyncLoad then
        self:asyncLoad_()
    else
        self:layout_()
    end

    return self
end

-- start --

--------------------------------
-- 取一个空闲项出来,如果没有返回空
-- @function [parent=#UIListView] dequeueItem
-- @return UIListViewItem#UIListViewItem  item
-- @see UIListViewItem

-- end --

function UIListView:dequeueItem()
    if #self.itemsFree_ < 1 then
        return
    end

    local item
    item = table.remove(self.itemsFree_, 1)

    --标识从free中取出,在loadOneItem_中调用release
    --这里直接调用release,item会被释放掉
    item.bFromFreeQueue_ = true

    return item
end

function UIListView:layout_()
    local width, height = 0, 0
    local itemW, itemH = 0, 0
    local margin

    -- calcate whole width height
    if UIScrollView.DIRECTION_VERTICAL == self.direction then
        width = self.viewRect_.width

        for i,v in ipairs(self.items_) do
            itemW, itemH = v:getItemSize()
            itemW = itemW or 0
            itemH = itemH or 0

            height = height + itemH
        end
    else
        height = self.viewRect_.height

        for i,v in ipairs(self.items_) do
            itemW, itemH = v:getItemSize()
            itemW = itemW or 0
            itemH = itemH or 0

            width = width + itemW
        end
    end
    self:setActualRect({x = self.viewRect_.x,
        y = self.viewRect_.y,
        width = width,
        height = height})
    self.size.width = width
    self.size.height = height

    local tempWidth, tempHeight = width, height
    if UIScrollView.DIRECTION_VERTICAL == self.direction then
        itemW, itemH = 0, 0

        local content
        for i,v in ipairs(self.items_) do
            itemW, itemH = v:getItemSize()
            itemW = itemW or 0
            itemH = itemH or 0

            tempHeight = tempHeight - itemH
            content = v:getContent()
            content:setAnchorPoint(0.5, 0.5)
            -- content:setPosition(itemW/2, itemH/2)
            self:setPositionByAlignment_(content, itemW, itemH, v:getMargin())
            v:setPosition(self.viewRect_.x,
                self.viewRect_.y + tempHeight)
        end
    else
        itemW, itemH = 0, 0
        tempWidth = 0

        for i,v in ipairs(self.items_) do
            itemW, itemH = v:getItemSize()
            itemW = itemW or 0
            itemH = itemH or 0

            content = v:getContent()
            content:setAnchorPoint(0.5, 0.5)
            -- content:setPosition(itemW/2, itemH/2)
            self:setPositionByAlignment_(content, itemW, itemH, v:getMargin())
            v:setPosition(self.viewRect_.x + tempWidth, self.viewRect_.y)
            tempWidth = tempWidth + itemW
        end
    end

    self.container:setPosition(0, self.viewRect_.height - self.size.height)
end

function UIListView:notifyItem(point)
    local count = self.listener[UIListView.DELEGATE](self, UIListView.COUNT_TAG)
    local temp = (self.direction == UIListView.DIRECTION_VERTICAL and self.container:getContentSize().height) or 0
    local w,h = 0, 0
    local tag = 0

    for i = 1, count do
        w,h = self.listener[UIListView.DELEGATE](self, UIListView.CELL_SIZE_TAG, i)
        if self.direction == UIListView.DIRECTION_VERTICAL then
            temp = temp - h
            if point.y > temp then
                point.y = point.y - temp
                tag = i
                break
            end
        else
            temp = temp + w
            if point.x < temp then
                point.x = point.x + w - temp
                tag = i
                break
            end
        end
    end

    if 0 == tag then
        printInfo("UIListView - didn't found item")
        return
    end

    local item = self.container:getChildByTag(tag)
    self.listener[UIListView.DELEGATE](self, UIListView.CLICKED_TAG, tag, point)
end

function UIListView:moveItems(beginIdx, endIdx, x, y, bAni)
    if 0 == endIdx then
        self:elasticScroll()
    end

    local posX, posY = 0, 0

    local moveByParams = {x = x, y = y, time = 0.2}
    for i=beginIdx, endIdx do
        if bAni then
            if i == beginIdx then
                moveByParams.onComplete = function()
                    self:elasticScroll()
                end
            else
                moveByParams.onComplete = nil
            end
            transition.moveBy(self.items_[i], moveByParams)
        else
            posX, posY = self.items_[i]:getPosition()
            self.items_[i]:setPosition(posX + x, posY + y)
            if i == beginIdx then
                self:elasticScroll()
            end
        end
    end
end

function UIListView:notifyListener_(event)
    if not self.touchListener_ then
        return
    end

    self.touchListener_(event)
end

function UIListView:modifyItemSizeIf_(item)
    local w, h = item:getItemSize()

    if UIScrollView.DIRECTION_VERTICAL == self.direction then
        if w ~= self.viewRect_.width then
            item:setItemSize(self.viewRect_.width, h, true)
        end
    else
        if h ~= self.viewRect_.height then
            item:setItemSize(w, self.viewRect_.height, true)
        end
    end
end

function UIListView:update_(dt)
    UIListView.super.update_(self, dt)

    self:checkItemsInStatus_()
    if self.bAsyncLoad then
        self:increaseOrReduceItem_()
    end
end

function UIListView:checkItemsInStatus_()
    if not self.itemInStatus_ then
        self.itemInStatus_ = {}
    end

    local rectIntersectsRect = function(rectParent, rect)
        -- dump(rectParent, "parent:")
        -- dump(rect, "rect:")

        local nIntersects -- 0:no intersects,1:have intersects,2,have intersects and include totally
        local bIn = rectParent.x <= rect.x and
                rectParent.x + rectParent.width >= rect.x + rect.width and
                rectParent.y <= rect.y and
                rectParent.y + rectParent.height >= rect.y + rect.height
        if bIn then
            nIntersects = 2
        else
            local bNotIn = rectParent.x > rect.x + rect.width or
                rectParent.x + rectParent.width < rect.x or
                rectParent.y > rect.y + rect.height or
                rectParent.y + rectParent.height < rect.y
            if bNotIn then
                nIntersects = 0
            else
                nIntersects = 1
            end
        end

        return nIntersects
    end

    local newStatus = {}
    local 
                       
                    
                    

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
【wireshark】插件开发(四):Lua插件Post-dissector和Listener发布时间:2022-07-22
下一篇:
修改Lua支持中文变量名发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap