cocos2dx-js 多层级列表

来源:互联网 发布:京东大数据 用户画像 编辑:程序博客网 时间:2024/05/18 03:08

先上图:


如上图所示,多层级列表可以展开其子层级列表.


cocos2dx中有一个TableView,使用它制作列表是一个比较好的选择.
一般使用TableView制作的都是一级列表,这里利用TableView来制作一个多层级列表.
下面直接上代码:

文件CommonList.js:
/**
 * 多级列表
 * 默认只渲染一级列表项
 * 渲染多级时,子列表数据必须放在sub_items数组中,如 {txt:"item 1", sub_items:[{txt:"sub item 1"},...]}
 * 且将enable_sub_item设置为true,该值默认为false
 */
var CommonList = cc.Node.extend({
    m_pTView : null,
    m_pTVSize : null,   //视图尺寸
    m_pTVRect : null,


    _sourceData : [],   //源数据
    _itemData : [],     //项数据
    _itemSize : [],     //项尺寸
    _itemPrefab : [],   //项资源
    enable_sub_item : false,
    _cellsFreed : [],   //空闲项
    _viewDelegate: null,


    ctor : function(view_size) {
        this._super();
        this.init(view_size);
    },
    init : function(view_size) {
        var self = this;
        self.m_pTVSize = view_size;
        self.setContentSize(self.m_pTVSize);
        self.m_pTVRect = cc.rect(0, 0, self.m_pTVSize.width, self.m_pTVSize.height);
        self.m_pTView = new cc.TableView(self, self.m_pTVSize);
        self.m_pTView.setDirection(cc.SCROLLVIEW_DIRECTION_VERTICAL);
        self.m_pTView.setVerticalFillOrder(cc.TABLEVIEW_FILL_TOPDOWN);
        self.m_pTView.setDelegate(self);
        self.addChild(self.m_pTView);
    },
    /**
     * 加载项资源,必须在loadData之前调用
     * @param res
     * @param width
     * @param height
     */
    addItemPrefab : function(res, width, height) {
        this._itemPrefab.push(res);
        var res_size = cc.size(width, height);
        this._itemSize.push(res_size);
    },
    /**
     * 设置外部委托,必须在loadData之前调用
     * @param delegate
     * ->delegate.setItem(node, data)            [必须]
     * ->delegate.onItemClick(node, data)        [可无]
     * ->delegate.onItemPressDown(node, data)    [可无]
     * ->delegate.onItemPressUp(node, data)      [可无]
     */
    setDelegate:function (delegate) {
        this._viewDelegate = delegate;
    },
    enableSubItem : function(tag) {
        this.enable_sub_item = tag;
    },


    //print
    printContainer : function () {
        var size = this.getContainer().getContentSize();
        console.log("->current container size : [ " + size.width + ", " + size.height + " ]");
        var pos = this.getContentOffset();
        console.log("->current container pos : [ " + pos.x + ", " + pos.y + " ]");
    },
    reloadData : function (dataSet) {
        //if(typeof (dataSet) != 'array') {
        //    cc.log("->reloadData(parameter) : invalid parameter");
        //    return;
        //}
        this._sourceData = dataSet;
        this.resetData(this._sourceData, 0);
        this.loadData();
    },
    loadData: function() {
        this._itemData = [];
        this.getItemData(this._sourceData);
        this.m_pTView.reloadData();
        this.printContainer();
    },
    getItemData : function(dataSet) {
        if(!dataSet || dataSet.length === 0) {
            return;
        }
        for(var i = 0, len = dataSet.length; i < len; ++i) {
            this._itemData.push(dataSet[i]);
            if(this.enable_sub_item && dataSet[i]._itemOpen && dataSet[i].sub_items) {
                this.getItemData(dataSet[i].sub_items);
            }
        }
    },
    resetData : function(dataSet, itemType) {
        if(!dataSet || dataSet.length === 0) {
            return;
        }
        for(var i = 0, len = dataSet.length; i < len; ++i) {
            dataSet[i]._itemLevel = itemType;       //层级(从0开始计算)
            dataSet[i]._itemOpen = false;           //展开标记
            dataSet[i]._itemIndex = i;              //当前层级下的索引(从0开始计算)
            dataSet[i]._itemCnt = dataSet.length;   //当前层级总计算
            if(this.enable_sub_item && dataSet[i].sub_items) {
                this.resetData(dataSet[i].sub_items, itemType + 1);
            }
        }
    },


    //tv
    getContainer : function() {
        return this.m_pTView.getContainer();
    },
    getContentOffset: function () {
        return this.m_pTView.getContentOffset();
    },
    setContentOffset: function (offset_pos) {
        this.m_pTView.setContentOffset(offset_pos);
    },
    dequeueCell:function (itemType) {
        if (this._cellsFreed.length === 0) {
            return null;
        } else {
            var ind = -1;
            for(var i = 0; i < this._cellsFreed.length; ++i) {
                if(this._cellsFreed[i]._itemType == itemType) {
                    ind = i;
                    break;
                }
            }
            if(ind == -1) {
                return null;
            }else {
                var cell = this._cellsFreed[ind];
                this._cellsFreed.splice(ind, 1);
                return cell;
            }
        }
    },
    closeItem: function (data) {
        data._itemOpen = false;
        if(data.sub_items && 0 < data.sub_items.length) {
            for(var ind = 0; ind < data.sub_items.length; ++ind) {
                this.closeItem(data.sub_items[ind]);
            }
        }
    },
    //-----------------------table view callback begin-------------------------//
    //ok
    numberOfCellsInTableView: function (table) {
        return this._itemData.length;
    },
    //ok
    tableCellSizeForIndex: function (table, idx) {
        var data = this._itemData[idx];
        var size = this._itemSize[data._itemLevel];
        if(!size) {
            cc.log("tableCellSizeForIndex: invalid return value");
        }
        return size;
    },
    //ok
    tableCellAtIndex: function (table, idx) {
        //cc.log("cell at index: " + idx);
        var data = this._itemData[idx];
        var itemType = 0;
        if(this.enable_sub_item && data._itemLevel) {
            itemType = data._itemLevel;
        }
        var res_item = this._itemPrefab[itemType];
        if(!res_item) {
            cc.log("tableCellAtIndex: invalid item prefab");
        }
        var cell = this.dequeueCell(itemType);
        if(!cell) {
            cell = new cc.TableViewCell();
            var json = ccs.load(res_item);
            var itemNode = json.node;
            cell.addChild(itemNode);
            cell._itemType = itemType;
            cell._itemNode = itemNode;
        }
        if(this._viewDelegate !== null && this._viewDelegate.setItem) {
            this._viewDelegate.setItem(cell._itemNode, data, cell._itemType);
        }
        return cell;
    },
    //ok
    tableCellTouched:function (table, cell) {
        var idx = cell.getIdx();
        var data = this._itemData[idx];
        if(!data) {
            cc.log("invalid item data");
            return;
        }
        var reload = false;
        if(this.enable_sub_item) {
            if(data.sub_items && 0 < data.sub_items.length) {
                data._itemOpen = data._itemOpen ? false : true;
                reload = true;
                //收缩其所有子项
                if(!data._itemOpen) {
                    this.closeItem(data);
                }
            }else {
                data._itemOpen = false;
            }
        }
        //if(this._viewDelegate !== null && this._viewDelegate.onItemClick) {
        //    this._viewDelegate.onItemClick(cell._itemNode, data);
        //}
        if(reload) {
            var ccp_offset = this.getContentOffset();
            var size_offset = this.getContainer().getContentSize();
            this.loadData();
            var size = this.getContainer().getContentSize();
            var of_y = size_offset.height - size.height + ccp_offset.y;
            this.setContentOffset(cc.p(0, of_y));
        }else {
            if(this._viewDelegate !== null && this._viewDelegate.onItemClick) {
                this._viewDelegate.onItemClick(cell._itemNode, data);
            }
        }
    },
    //ok
    tableCellHighlight:function(table, cell){
        var idx = cell.getIdx();
        if(this._viewDelegate !== null && this._viewDelegate.onItemPressDown) {
            var data = this._itemData[idx];
            this._viewDelegate.onItemPressDown(cell._itemNode, data);
        }
    },
    //ok
    tableCellUnhighlight: function(table, cell){
        var idx = cell.getIdx();
        if(this._viewDelegate !== null && this._viewDelegate.onItemPressUp) {
            var data = this._itemData[idx];
            this._viewDelegate.onItemPressUp(cell._itemNode, data);
        }
    },
    //ok
    tableCellWillRecycle: function(table, cell) {
        this._cellsFreed.push(cell);
    }
    //-----------------------table view callback end-------------------------//


});


使用示例:
var list_size = cc.size(560, 800);
var common_list = new CommonList(list_size); 
list_layer.addChild(common_list);


设置项资源
common_list.addItemPrefab(res.UIItemPrefab_1, 551, 54);
common_list.addItemPrefab(res.UIItemPrefab_2, 551, 54);


设置委托
var list_delegate = {};
list_delegate.setItem = function (node, data) {
    var level = data._itemLevel;
    if(level == 0) {
        var _bg = node.getChildByName("bg");
        var _txt_1 = _bg.getChildByName("txt_1");
        _txt_1.ignoreContentAdaptWithSize(true);
        var _txt_2 = _bg.getChildByName("txt_2");
        _txt_2.ignoreContentAdaptWithSize(true);


        _txt_1.setString(data.txt_1);
        _txt_2.setString(data.txt_2);
    }else if(level == 1) {
        var _bg = node.getChildByName("bg");
        var _txt_1 = _bg.getChildByName("txt_1");
        _txt_1.ignoreContentAdaptWithSize(true);


        _txt_1.setString(data.txt);
    }
};
list_delegate.onItemClick = function (node, data) {
    cc.log("->list_delegate.onItemClick");
};
list_delegate.onItemPressDown = function (node, data) {
    cc.log("->list_delegate.onItemPressDown");
};
list_delegate.onItemPressUp = function (node, data) {
    cc.log("->list_delegate.onItemPressUp");
};
common_list.setDelegate(list_delegate);

//启用多层级,否则它只是一级列表
common_list.enableSubItem(true);

加载数据, 注意数据格式限制,子项必须包含在 sub_items数组中
var list_dataSet = [
    {txt_1: "10倍场", txt_2:"9824人", sub_items:[{txt:"房间 1"},{txt:"房间 2"},{txt:"房间 3"},{txt:"房间 4"}]},
    {txt_1: "100倍场", txt_2:"754人", sub_items:[{txt:"test"}]},
    {txt_1: "1000倍场", txt_2:"2345人", sub_items:[{txt:"test 1"},{txt:"test 2"},{txt:"test 3"}]},
    {txt_1: "10000倍场", txt_2:"678人", sub_items:[{txt:"挑战 1"},{txt:"挑战 2"}]}
];
common_list.reloadData(list_dataSet);

至此,恭喜你创建出多层级列表.

0 0
原创粉丝点击