自己写的单选框(原生的选文字不能触发单选动作)

1、点击文字可以触发单选动作;
2、扩大了选择区域;

使用:

new Radio({
            parent: cc.find("Canvas"),
            radios: [{
                name: "radio1",
                text: "radio1",
                fontSize: 50,
                x: -200,
                y: 255,
                checked: true
            }, {
                name: "radio2",
                text: "radio2",
                fontSize: 50,
                x: 200,
                y: 255,
                checked: false
            }]
        });

代码:

cc.Class({
    extends: cc.Component,

    properties: {},

    ctor: function () {

        this._opts = {
            parent: null,
            radios: [{
                name: "radio1",
                text: "radio1",
                fontSize: 40,
                x: 0,
                y: 0,
                checked: true
            }, {
                name: "radio2",
                text: "radio2",
                fontSize: 40,
                x: 300,
                y: 0,
                checked: false
            }],
            onRadioChange: undefined
        };

        cc.js.mixin(this, {
            _radioChecked: undefined,
            _radioUnchecked: undefined
        });

        cc.js.mixin(this._opts, arguments[0]);

        this._radioObjects = {};
        for (var i = 0; i < this._opts.radios.length; i++) {
            this._radioObjects[this._opts.radios[i].name] = {
                opt: this._opts.radios[i]
            };
        }

        this.waitCalls([this.loadCheckRes.bind(this), this.loadUncheckRes.bind(this)], function () {

            var radios = this._opts.radios;
            for (var i = 0; i < radios.length; i++) {
                this.newRadio(cc.js.mixin({parent: this._opts.parent}, radios[i]));
            }

        }.bind(this));

        this._opts.parent.on(cc.Node.EventType.TOUCH_START, this.onParentTouchStart.bind(this));

    },

    loadCheckRes: function (handler) {
        cc.loader.loadRes("textures/icon/radio-checked.png", cc.SpriteFrame, function (err, frame) {
            this._radioChecked = frame;
            handler();
        }.bind(this));
    },

    loadUncheckRes: function (handler) {
        cc.loader.loadRes("textures/icon/radio-unchecked.png", cc.SpriteFrame, function (err, frame) {
            this._radioUnchecked = frame;
            handler();
        }.bind(this));
    },

    charSum: function (chars) {
        var sum = 0;
        for (var i = 0; i < chars.length; i++) {
            var c = chars.charCodeAt(i);
            if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
                sum++;
            }
            else {
                sum += 2;
            }
        }
        return sum;
    },

    /**
     *
     *
     * node
     *      ---img
     *      ---node
     *          ---label
     *
     * @param opts
     */

    newRadio: function (opts) {
        var node = new cc.Node();

        var img = node.addComponent(cc.Sprite);
        img.spriteFrame = opts.checked ? this._radioChecked : this._radioUnchecked;

        var radio = new cc.Node();
        var lab = radio.addComponent(cc.Label);
        lab.string = opts.text;
        lab.fontSize = opts.fontSize || 40;
        lab.lineHeight = opts.fontSize || 40;

        //一个中文对应的宽度==fontSize,一个英文对应的宽度对应fontSize/2
        //这里中文占两个字符,英文一个
        //所以总字符数需要/2得到全部转换成中文字符的数量
        var sum = this.charSum(lab.string) / 2;

        //画布以中心为原点,/2得到原点位置
        //再加上前面的图标的宽度
        //最后得到标签的位置
        lab.node.setPosition(sum * lab.fontSize / 2 + img.node.width, 4);

        node.addChild(radio);

        node.name = opts.name;
        node.setPosition(opts.x, opts.y);


        cc.js.mixin(this._radioObjects[opts.name], {
            node: node
        });

        opts.parent.addChild(node);
    },

    waitCalls: function (calls, handler) {

        var counter = 0;
        var fn = function () {
            if (++counter >= calls.length) {
                handler();
            }
        };

        for (var i = 0; i < calls.length; i++) {
            calls[i](fn);
        }
    },

    onParentTouchStart: function (e) {
        var point = e.getLocation();

        for (var l in this._radioObjects) {
            var opt = this._radioObjects[l].opt;
            var node = this._radioObjects[l].node;
            var img = node.getComponent(cc.Sprite);

            //加大点击时可触发的范围
            var rect = node.getBoundingBoxToWorld();
            rect.x -= 16;
            rect.y -= 16;
            rect.width += 32;
            rect.height += 32;

            if(cc.rectContainsPoint(rect, point)) {
                this.clearRadioSets();

                opt.checked = true;
                img.spriteFrame = this._radioChecked;
                node.getChildren(cc.Label)[0].setColor(new cc.Color(255, 0, 0));

                break;
            }
        }
    },

    clearRadioSets: function () {
        for (var l in this._radioObjects) {
            this._radioObjects[l].opt.checked = false;
            var img = this._radioObjects[l].node.getComponent(cc.Sprite);
            img.spriteFrame = this._radioUnchecked;
            var lab = this._radioObjects[l].node.getChildren(cc.Label);
            lab[0].setColor(new cc.Color(255, 255, 255));
        }
    },

    currentRadio: function () {
        var radios = this._opts.radios;

        for(var i = 0; i < radios.length; i++) {
            var radio = radios[i];
            if(radio.checked) {
                return radio;
            }
        }
    }
});

你想太多了,你把文字作为toggle的子节点,然后把toggle的大小设置一下,包含toggle和文字就行了:sweat_smile:

点击区域是根据toggle组件所在节点的大小来计算的