自定义的Toggle和Radio组件(附代码和用法)

var ToggleType = cc.Enum({
    NONE          : 0,     //无
    TOGGLE        : 1,     //复选框
    RADIO         : 2,     //单选
})

cc.Class({
    extends: cc.Component,
    
    properties: {
        toggleType   : {
            default : ToggleType.NONE,
            type : ToggleType,
        },
        
        defaultSelectedNode : {
            default : [],
            type : cc.Node,
        },
        
        clickEvents  : {
            default : [],
            type : cc.Component.EventHandler,
        },
    },
    
    onLoad () {
        if(this.toggleType == ToggleType.NONE) {
            cc.error("Error: toggle type should not be NONE")
            return
        }
    
        this.selectedNode = []
        this.baseToggleList = this.getButtonList()
        
        var self = this
        for(var index = 0; index < this.baseToggleList.length; index++){
            this.baseToggleList[index].on('click', function (event) {
                self.toggleClicked(event.target)
            })
        }
        
        this.showDefault()
    },
    
    getButtonList(){
        var nodeList = []
        for (var index = 0; index < this.node.childrenCount; index ++){
            var child = this.node.children[index]
            var component = child.getComponent(cc.Button) || null
            if(component) {
                nodeList.push(child)
            }
        }
        
        return nodeList
    },

    toggleClicked (target){
        var strNameArray = target.name.split("_")
        var selected_index = strNameArray[strNameArray.length - 1]
        var isSelectedNode = this.isSelected(target)
        if(this.toggleType == ToggleType.RADIO) {
            //单选框
            if(!isSelectedNode) {
                //先隐藏旧有的,然后再显示现在的
                this.showSelected(this.selectedNode[0], false)
                this.showSelected(target, true)
            }
        } else if(this.toggleType == ToggleType.TOGGLE) {
            this.showSelected(target, !isSelectedNode)
        }
        
        this.emitClickInfo()
    },
    
    emitClickInfo : function(){
        var selectedIndex = this.getSelectedNodesIndex()
        for(var index = 0; index < this.clickEvents.length; index++){
            if(this.toggleType == ToggleType.TOGGLE) {
                this.clickEvents[index].emit([selectedIndex])
            } else {
                this.clickEvents[index].emit(selectedIndex)
            }
        }
    },
    
    isSelected (target) {
        for(var index = 0; index < this.selectedNode.length; index++) {
            var node = this.selectedNode[index]
            if(node.name === target.name) {
                // var mark = node.getChildByName("sp_mark")
                return true
            }
        }
        return false
    },
    
    showSelected (node, bSelected) {
        var mark = node.getChildByName("sp_mark")
        if(mark){
            mark.active = bSelected
        }
        
        if(bSelected) {
            //添加新的选中节点
            this.selectedNode.push(node)
        } else {
            //移除已经取消选中的
            for(var index = 0; index < this.selectedNode.length; index++) {
                if(this.selectedNode[index].name === node.name) {
                    this.selectedNode.splice(index,1)
                    break
                }
            }
        }
    },
    
    
    showDefault () {
        var self = this
        var isDefaultSelected = function (target) {
            for(var index = 0; index < self.defaultSelectedNode.length; index++) {
                var node = self.defaultSelectedNode[index]
                if(node.name === target.name) {
                    return true
                }
            }
            return false
        }
        for(var index = 0; index < this.baseToggleList.length; index++){
            var node = this.baseToggleList[index]
            this.showSelected(node, isDefaultSelected(node))
        }
        
        this.emitClickInfo();
    },
    
    getSelectedNodesIndex () {
        var list = []
        for(var index = 0; index < this.selectedNode.length; index++) {
            var node = this.selectedNode[index]
            var nameCaches = node.name.split("_")
            list.push(parseInt(nameCaches[nameCaches.length - 1]))
        }
        return list
    },
    
    //跳转到对应索引的节点
    switchByIndex (index) {
        for(var index = 0; index < this.baseToggleList.length; index++) {
            var node = this.baseToggleList[index]
            var nameCaches = node.name.split("_")
            var targetIdx = parseInt(nameCaches[nameCaches.length - 1]) 
            if(targetIdx == index){
                this.switchByNode(node)
            }
        }
    },

    //跳转到对应节点
    switchByNode (button) {
        this.toggleClicked(button)
    },
    
})

1.按键结构 : 一个按钮组件 + 一个名为sp_mark的子节点,选中的状态下sp_mark的子节点显示,未选中则不显示
2.defaultSelectedNode 为默认需要选中的按钮列表,ToggleType 为TOGGLE时可以选择多个,RADIO只能选中一个
3.回调就不用说了,跟普通按键的回调一样,但是会返回你当前所选中的所有节点
4.按键命名规则为: 名字+下划线+编号 , 如"btnAbc_1""btnAbc_2"“btnAbc_3”, ,回调的时候返回的内容就是1,2,3中的一个或者多个
5.组件挂载在按键组的父节点上

非常简单的小东西,个人用起来比较方便,就给大家分享下

和官方的toggle组件相比,有哪些优点?有哪些缺点?