cocos2dx-lua使用UIListView制作二级折叠菜单
折叠菜单,用过jquery accordion的同学都知道是啥玩艺儿~,图片效果就是介样:
cocos2dx不带有此控件,因此我们动手来实现一个。
原理很简单,展开的时候往listview里insertCustomItem,收起的时候从listview里removeItem。下面给出一个功能丰富的折叠菜单控件。
先看控件主类:
- --[[
- 二级折叠菜单组
- 构造:
- local groupData = {
- {
- title = '分类1',
- items = {
- { id = 1, count = 20, lv = 19 },
- { id = 2, count = 21, lv = 21 },
- { id = 3, count = 22, lv = 23 },
- }
- },
- {
- title = '图腾',
- items = {
- { id = 500001, count = 32, lv = 19 },
- { id = 500002, count = 21, lv = 65 },
- { id = 500003, count = 22, lv = 27 },
- }
- },
- {
- title = '武器',
- items = {
- { id = 101002, count = 20, lv = 45 },
- { id = 101003, count = 21, lv = 34 },
- }
- },
- }
- self._goodsCateList = gm.Common.UIMenuList.new( cc.size( 310, 510 ), groupData )
- -- 必须设置标题类型和内容类型,重写可改变样式
- self._goodsCateList:setClass( gm.Market.MarketMenuTitle, gm.Market.MarketMenuItem )
- -- 可选参数,是否可同时展开多个分组,默认false
- self._goodsCateList.showMulti = true
- -- 可选参数,是否默认选中组中第一个item
- self._goodsCateList.autoSelectFirstItem = true
- -- 可选参数,选中的title索引,默认为1
- self._goodsCateList.defaultGroup = 1
- -- 可选参数,选中的item索引,默认为1
- self._goodsCateList.defaultItem = 1
- 加入舞台:
- self._goodsCateList:addToParent( self._bg, { x = 0, y = 0 } )
- @author cc
- --]]
- gm = gm or {}
- rm = rm or {}
- local gm = gm
- local rm = rm
- gm.Common = gm.Common or {}
- gm.Common.UIMenuList = class( "Common.UIMenuList" )
- gm.Common.UIMenuList._name = "Common.UIMenuList"
- local g = gm.Common.UIMenuList
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义私有部分 --
- -- --
- ---------------------------------------------------------------------------------
- local function log( ... )
- print( '>>>>gm.Common.UIMenuList<<<<:', ...)
- end
- -- 点击标题项
- function g:_onTouchTitle( sender )
- local titleInst = sender._inst
- -- 收缩点击项
- if titleInst.selected then
- self:_unSelectTitleInst( titleInst )
- return
- end
- -- 如果同时只展开一个分组,则隐藏上次展开的
- if not self._showMulti and self._selectedTitle then
- self:_unSelectTitleInst( self._selectedTitle )
- end
- -- 展开点击项
- local index = self._listView:getIndex( sender )
- local group = titleInst.data
- local itemInst
- for itemIdx, itemData in ipairs( group.items ) do
- itemInst = self:_createItemInst( itemData )
- self._listView:insertCustomItem( itemInst.ui, index + itemIdx )
- -- 将第一项设置为当前选中的内容项
- if self._autoSelectFirstItem and itemIdx == then
- self.selectedItem = itemInst
- end
- end
- -- 设置当前选中的标题项
- self.selectedTitle = titleInst
- end
- -- 点击内容项
- function g:_onTouchItem( sender, eventType )
- if eventType == ccui.TouchEventType.ended then
- self.selectedItem = sender._inst
- end
- if self._itemClickFunc then
- self._itemClickFunc( sender, eventType )
- end
- end
- -- 收起标题项对应的分组
- function g:_unSelectTitleInst( titleInst )
- local index = self._listView:getIndex( titleInst.ui )
- local group = titleInst.data
- local itemInst
- for i = , #group.items do
- -- 析构删除项
- itemInst = self._listView:getItem( index + )._inst
- itemInst:finalize()
- -- 选中项被删除
- if self._selectedItem and self._selectedItem == itemInst then
- self._selectedItem = nil
- end
- self._listView:removeItem( index + )
- end
- titleInst.selected = false
- if titleInst == self._selectedTitle then
- self._selectedTitle = nil
- end
- end
- -- 创建标题项
- function g:_createTitleInst( data )
- if not self._titleCls then
- log( '没有设置标题类型!' )
- return
- end
- local titleInst = self._titleCls.new( )
- titleInst.data = data
- titleInst.ui._inst = titleInst
- makeTouchHandle( self, titleInst.ui, self._onTouchTitle )
- return titleInst
- end
- -- 创建内容项
- function g:_createItemInst( data )
- if not self._itemCls then
- log( '没有设置内容类型!' )
- return
- end
- local itemInst = self._itemCls.new( )
- itemInst.data = data
- itemInst.ui._inst = itemInst
- makeTouchHandle2( self, itemInst.ui, self._onTouchItem )
- return itemInst
- end
- -- 初始化
- function g:_initialize( )
- self._listView = ccui.ListView:create()
- self._listView:setBounceEnabled( true )
- self._listView:setDirection( ccui.ScrollViewDir.vertical )
- self._listView:setSize( self._size )
- if not self._groupData then
- log( '分组数据为空!' )
- return
- end
- local titleInst, itemInst
- self._titleInstList = {}
- for groupIdx, group in ipairs( self._groupData ) do
- titleInst = self:_createTitleInst( group )
- self._listView:pushBackCustomItem( titleInst.ui )
- table.insert( self._titleInstList, titleInst )
- -- 展开默认分组
- if self._defaultGroupIdx and groupIdx == self._defaultGroupIdx then
- self.selectedTitle = titleInst
- for itemIdx, itemData in ipairs( group.items ) do
- itemInst = self:_createItemInst( itemData )
- self._listView:pushBackCustomItem( itemInst.ui )
- -- 选中默认项
- if self._defaultItemIdx and itemIdx == self._defaultItemIdx then
- self.selectedItem = itemInst
- end
- end
- end
- end
- end
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义set, get 部分函数 --
- -- --
- ---------------------------------------------------------------------------------
- function g:_getUi( )
- return self._listView
- end
- -- 是否同时展开多个组
- function g:_setShowMulti( value )
- self._showMulti = value
- end
- -- 获取数据
- function g:_getGroupData( )
- return self._groupData
- end
- function g:_setGroupData( value )
- self._groupData = value
- end
- -- 设置默认展开的分组索引
- -- @i value
- function g:_setDefaultGroup( value )
- self._defaultGroupIdx = value
- end
- -- 设置默认选中的item索引
- --@i value
- function g:_setDefaultItem( value )
- self._defaultItemIdx = value
- end
- -- 获取选中的标题项
- function g:_getSelectedTitle( )
- return self._selectedTitle
- end
- function g:_setSelectedTitle( value )
- value.selected = true
- self._selectedTitle = value
- rm.BindManager.propertyChanged( self, "selectedTitle" )
- end
- -- 获取选中的内容项
- function g:_getSelectedItem( )
- return self._selectedItem
- end
- function g:_setSelectedItem( value )
- if self._selectedItem then
- self._selectedItem.selected = false
- end
- value.selected = true
- self._selectedItem = value
- rm.BindManager.propertyChanged( self, "selectedItem" )
- end
- -- 设置点击item项的回调函数
- function g:_setItemClickFunc( value )
- self._itemClickFunc = value
- end
- -- 设置是否自动选中组中第一个item
- function g:_setAutoSelectFirstItem( value )
- self._autoSelectFirstItem = value
- end
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义公共部分 --
- -- --
- ---------------------------------------------------------------------------------
- -- 构造
- -- @t size cc.size类型
- -- @t groupData 分组数据,结构如{ { title = tData, items = { iData1, iData2 } }, ... }
- function g:ctor( size, groupData )
- self._size = size or cc.size( , )
- self._groupData = groupData
- self._titleInstList = nil
- self._defaultGroupIdx = nil
- self._defaultItemIdx = nil
- self._selectedTitle = nil
- self._selectedItem = nil
- self._titleCls = nil
- self._itemCls = nil
- self._showMulti = false
- self._autoSelectFirstItem = false
- self._itemClickFunc = nil
- end
- -- 设置标题项和内容项类型
- -- @t titleClass 继承自gm.Common.UIMenuItem,重写可改变样式
- -- @t itemClass 继承自gm.Common.UIMenuItem,重写可改变样式
- function g:setClass( titleClass, itemClass )
- self._titleCls = titleClass
- self._itemCls = itemClass
- end
- -- 添加到舞台
- -- @widget parent 父显示对象
- -- @t pos 位置,{ x = , y = }
- -- @i zOrder 层级
- function g:addToParent( parent, pos, zOrder )
- if not parent then
- log( '父显示对象不可为空!' )
- return
- end
- self:_initialize()
- zOrder = zOrder or
- pos = pos or cc.p( , )
- self._listView:setPosition( pos )
- parent:addChild( self._listView, zOrder )
- end
- -- 刷新当前展开的分组,只可在互斥(showMulti = false)模式下使用
- -- @t group 数据,结构如{ title = tData, items = { iData1, iData2 } }
- function g:refreshSelectedTitle( group )
- if not self._selectedTitle then return end
- self:refreshTitle( self._selectedTitle, group )
- end
- -- 刷新指定位置的分组
- -- @i titleIndex 分组索引
- -- @t group 组数据
- function g:refreshTitleAtIndex( titleIndex, group )
- local title = self._titleInstList( titleIndex )
- self:refreshTitle( title, group )
- end
- -- 刷新指定分组
- -- @t 某个分组
- -- @t group 组数据
- function g:refreshTitle( title, group )
- local index = self._listView:getIndex( title.ui )
- local prevNumItems = title.selected and #title.data.items or
- local currNumItems = #group.items
- local deltaNum = prevNumItems - currNumItems
- local itemInst
- -- 设置title数据
- title:_setData( group )
- self._groupData[ table.indexOf( self._titleInstList, title ) ] = group
- -- title没展开,以下无需执行
- if not title.selected then return end
- -- 设置item数据
- for itemIdx, itemData in ipairs( group.items ) do
- if itemIdx <= prevNumItems then
- itemInst = self._listView:getItem( index + itemIdx )._inst
- itemInst:_setData( itemData )
- else
- itemInst = self:_createItemInst( itemData )
- self._listView:insertCustomItem( itemInst.ui, index + itemIdx )
- end
- end
- -- 旧数量比当前数量多,需要删除多余的item
- if deltaNum > then
- for i = , deltaNum do
- itemInst = self._listView:getItem( index + currNumItems + )._inst
- itemInst:finalize()
- -- 选中项被删除
- if self._selectedItem and self._selectedItem == itemInst then
- self._selectedItem = nil
- end
- self._listView:removeItem( index + currNumItems + )
- end
- end
- end
- -- 刷新整个控件
- -- @t 控件数据,结构如构造函数同名参数所示
- function g:refresh( groupData )
- self._groupData = groupData
- if not self._groupData then
- log( '分组数据为空!' )
- return
- end
- local prevNumTitles = #self._titleInstList
- local currNumTitles = #groupData
- local deltaNum = prevNumTitles - currNumTitles
- local titleInst
- -- 刷新所有分组
- for groupIdx, group in ipairs( groupData ) do
- if groupIdx <= prevNumTitles then
- titleInst = self._titleInstList[ groupIdx ]
- self:refreshTitle( titleInst, group )
- else
- titleInst = self:_createTitleInst( group )
- self._listView:pushBackCustomItem( titleInst.ui )
- table.insert( self._titleInstList, titleInst )
- end
- end
- -- 新分组比旧分组少,需要删除多余的title
- if deltaNum > then
- local numListItems = #self._listView:getItems()
- -- 清空全部
- if currNumTitles == then
- for i = numListItems - , , - do
- titleInst = self._listView:getItem( i )._inst
- titleInst:finalize()
- end
- self._listView:removeAllItems()
- self._titleInstList = {}
- self._selectedTitle = nil
- self._selectedItem = nil
- return
- end
- local lastTitleInst = self._titleInstList[ currNumTitles ]
- local index = self._listView:getIndex( lastTitleInst.ui ) + ( lastTitleInst.selected and #lastTitleInst.data.items or )
- for i = numListItems - , index + , - do
- -- 析构被删除的title
- titleInst = self._listView:getItem( i )._inst
- titleInst:finalize()
- -- 选中title被删除
- if self._selectedTitle and self._selectedTitle == titleInst then
- self._selectedTitle = nil
- end
- -- 选中项被删除
- if self._selectedItem and self._selectedItem == titleInst then
- self._selectedItem = nil
- end
- self._listView:removeItem( i )
- end
- -- 从title列表中移除
- for i = prevNumTitles, currNumTitles + , - do
- table.remove( self._titleInstList, i )
- end
- end
- end
- -- 析构
- function g:finalize()
- if self._listView then
- self._listView:removeFromParent()
- self._listView = nil
- end
- self._titleInstList = nil
- self._groupData = nil
- self._itemClickFunc = nil
- end
我们把折叠菜单抽象成标题项(title)和内容项(item),title即指标题项,展开标题项显示出来的内容项叫item。title和item均从uimenuitem派生而来,这们做的好处是我们可以方便的更改折叠菜单标题项和内容项的样式。
下面来看看uimenuitem.lua:
- --[[
- 折叠菜单项
- @author cc
- --]]
- gm = gm or {}
- rm = rm or {}
- local gm = gm
- local rm = rm
- gm.Common = gm.Common or {}
- gm.Common.UIMenuItem = class( "Common.UIMenuItem" )
- gm.Common.UIMenuItem._name = "Common.UIMenuItem"
- local g = gm.Common.UIMenuItem
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义私有部分 --
- -- --
- ---------------------------------------------------------------------------------
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义set, get 部分函数 --
- -- --
- ---------------------------------------------------------------------------------
- -- 获取显示对象
- function g:_getUi( )
- return self._ui
- end
- function g:_getData( )
- return self._data
- end
- -- 设置数据
- function g:_setData( value )
- self._data = value
- end
- function g:_getSelected( )
- return self._selected
- end
- -- 设置选中状态
- function g:_setSelected( value )
- self._selected = value
- end
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义公共部分 --
- -- --
- ---------------------------------------------------------------------------------
- -- 构造
- function g:ctor( )
- self._selected = false
- self._data = nil
- self:initialize()
- end
- -- 初始化
- function g:initialize( )
- self._ui = nil
- end
- -- 析构
- function g:finalize( )
- if self._ui then
- self._ui:removeFromParent( )
- self._ui = nil
- end
- end
下面举个简单的使用例子,
- local groupData = {
- {
- title = { cate = , cate_desc = '技能书' },
- items = {
- {
- sub_cate = , sub_cate_desc = '一级技能书',
- },
- {
- sub_cate = , sub_cate_desc = '二级技能书',
- },
- {
- sub_cate = , sub_cate_desc = '三级技能书',
- }
- }
- },
- {
- title = { cate = , cate_desc = '宝石' },
- items = {
- {
- sub_cate = , sub_cate_desc = '攻击宝石',
- },
- {
- sub_cate = , sub_cate_desc = '暴击宝石',
- }
- }
- },
- {
- title = { cate = , cate_desc = '月石' },
- items = {
- {
- sub_cate = , sub_cate_desc = '很好的月石',
- }
- }
- },
- }
- self._goodsCateList = gm.Common.UIMenuList.new( cc.size( , ), groupData )
- self._goodsCateList:setClass( gm.Market.MarketMenuTitle, gm.Market.MarketMenuItem )
- self._goodsCateList.showMulti = true
- self._goodsCateList.defaultGroup =
- self._goodsCateList.defaultItem =
- self._goodsCateList:addToParent( self._bg, cc.p( , ) )
这里方便演示手写了分类数据,但一般情况下是用遍历生成的。通过上面这段代码,我们生成了一个折叠菜单,效果即本文首部的演示图片。
这里用到的两个类gm.Market.MarketMenuTitle和gm.Market.MarketMenuItem即是用来自定义折叠菜单样式的,代码也一块贴出:
- --[[
- 市场折叠菜单标题项
- @author cc
- --]]
- gm = gm or {}
- rm = rm or {}
- local gm = gm
- local rm = rm
- gm.Market = gm.Market or {}
- gm.Market.MarketMenuTitle = class( "Market.MarketMenuTitle", gm.Common.UIMenuItem )
- gm.Market.MarketMenuTitle._name = "Market.MarketMenuTitle"
- local g = gm.Market.MarketMenuTitle
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义私有部分 --
- -- --
- ---------------------------------------------------------------------------------
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义set, get 部分函数 --
- -- --
- ---------------------------------------------------------------------------------
- -- 设置数据
- function g:_setData( value )
- self._data = value
- self._labelName:setText( value.title.cate_desc )
- end
- -- 设置选中状态
- function g:_setSelected( value )
- self._selected = value
- local texture = value and 'tab_btn_4.png' or 'tab_btn_3.png'
- self._imgBg:loadTexture( texture, ccui.TextureResType.plistType )
- end
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义公共部分 --
- -- --
- ---------------------------------------------------------------------------------
- -- -- 构造
- -- function g:ctor( )
- -- g.super.ctor( self )
- -- end
- -- 初始化
- function g:initialize( )
- g.super.initialize( self )
- self._ui = ccs.GUIReader:getInstance():widgetFromJsonFile('ui/new_market_menu_title.json')
- self._labelName = self._ui:getChildByName('LabName')
- self._imgBg = self._ui:getChildByName('ImgBg')
- end
- -- -- 析构
- -- function g:finalize( )
- -- g.super.finalize( self )
- -- end
- --[[
- 市场折叠菜单内容项
- @author cc
- --]]
- gm = gm or {}
- rm = rm or {}
- local gm = gm
- local rm = rm
- gm.Market = gm.Market or {}
- gm.Market.MarketMenuItem = class( "Market.MarketMenuItem", gm.Common.UIMenuItem )
- gm.Market.MarketMenuItem._name = "Market.MarketMenuItem"
- local g = gm.Market.MarketMenuItem
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义私有部分 --
- -- --
- ---------------------------------------------------------------------------------
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义set, get 部分函数 --
- -- --
- ---------------------------------------------------------------------------------
- -- 设置数据
- function g:_setData( value )
- self._data = value
- self._labelName:setText( value.sub_cate_desc )
- end
- -- 设置选中状态
- function g:_setSelected( value )
- self._selected = value
- self._imgSelected:setVisible( value )
- end
- ---------------------------------------------------------------------------------
- -- --
- -- 以下定义公共部分 --
- -- --
- ---------------------------------------------------------------------------------
- -- 构造
- function g:ctor( )
- g.super.ctor( self )
- end
- -- 初始化
- function g:initialize( )
- g.super.initialize( self )
- self._ui = ccs.GUIReader:getInstance():widgetFromJsonFile('ui/new_market_menu_item.json')
- self._labelName = self._ui:getChildByName('LabName')
- self._imgSelected = self._ui:getChildByName('ImgSelected')
- end
- -- 析构
- function g:finalize( )
- g.super.finalize( self )
- end
cocos2dx-lua使用UIListView制作二级折叠菜单的更多相关文章
- DIV+CSS制作二级横向弹出菜单,略简单
没有使用JavaScript控制二级菜单的显示,结果如上图所示. 代码如下: <!DOCTYPE html> <html> <head> <meta char ...
- jQuery制作右侧边垂直二级导航菜单
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 个人练习:使用HTML+CSS制作二级菜单
最近一直在学习HTML+CSS,刚看完如果制作下拉菜单部分,就想着做一个练练手. 先上成品图: 就是上面这个效果,横向菜单选项能点击,鼠标放在上面也能展开二级菜单,二级菜单也能点击,点击后就会在底下的 ...
- Excel应用----制作二级下拉菜单【转】
应用: 原始数据源是两列的源数据,那该如何制作二级下拉菜单, 当然可以将这两列的数据源,转换成上面的那种格式,再用上面的方法来制作. 今天教大学的方法是直接通过这种两列式的数据源来制作下拉菜单,如果A ...
- CSS制作二级菜单时,二级菜单与一级菜单不对齐
效果如图: 部分代码如图: <li><a href="#" target="_blank">关于我们</a> <ul& ...
- dedecms模版制作活动的折叠菜单
需要做成这种样式 url请求为这样: http://m03.com/plus/list.php?tid=19 这些菜单项都有对应的tid项,页面刷新后,应该将所有的菜单折叠起来,对于tid=19的菜单 ...
- 滑动式折叠菜单 - Slashdot's Menu
折叠菜单让你在尽可能小的地方放置尽可能多的内容,同时加大了操作的简便性,因此,深受前台设计师的喜爱.随着大家对动画效果的钟爱,折叠菜单也开始“动”起来了,本文介绍的就是 DimX 制作的滑动式折叠菜单 ...
- Cocos2dx lua 3D实例代码
用cocoside 创建一个项目 cocos2dx lua 项目即可 ,然后替换掉gamescene 就可以,具体效果还有函数的参数,相信大家一看就明白.简单说下ide 创建的 cocos lua 项 ...
- 第一个Cocos2d-x Lua游戏
我们的编写的第一个Cocos2d-x Lua程序,命名为HelloLua,从该工程开始学习其它的内容.创建工程我们创建Cocos2d-x Lua工程可以通过Cocos2d-x提供的命令工具cocos实 ...
随机推荐
- JAVA逻辑字符串判断真假
package com.chinahrt.zyn.iteye; import javax.script.Bindings; import javax.script.Compilable; import ...
- HDU ACM 3177 Crixalis's Equipment
Crixalis's Equipment Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- Gridheh 垂直居中
Gridheh 垂直居中 上下居中 each columns set layout ColumnDefValues.Layout = tlCenter 有colResize,拖动调整列宽. 但是没有 ...
- 【转】玩转log4j
原文链接:http://www.cnblogs.com/shenliang123/archive/2012/05/02/2479286.html 由于最近正在扩展卫生局考务系统,由于上一次使用过一次该 ...
- HTML5每日一练之视频标签的应用
与音频一样,在过去,我们如果想在Web上播放视频,也是都是通过Flash来播放,同样并不是所有的浏览器都安装了Flash播放器插件,而现在我们在HTML5中,就能完全脱离Flash或其他的插件来播放视 ...
- USB的四种传输类型
USB协议规定了4种传输类型:批量(bulk)传输,等时传输(同步传输),中断传输和控制传输.
- hdu 1199 Color the Ball
http://acm.hdu.edu.cn/showproblem.php?pid=1199 Color the Ball Time Limit: 2000/1000 MS (Java/Others) ...
- AutoCAD.NET 不使用P/Invoke方式调用acad.exe或accore.dll中的接口(如acedCommand、acedPostCommand等)
使用C#进行AutoCAD二次开发,有时候由于C#接口不够完善,或者低版本AutoCAD中的接口缺少,有些工作不能直接通过C#接口来实现,所以需要通过P/Invoke的方式调用AutoCAD的其他DL ...
- flask中的request对象方法
'accept_charsets','accept_encodings','accept_languages','accept_mimetypes','access_route','applicati ...
- HDU 1242 Rescue (BFS(广度优先搜索))
Rescue Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...