自己实现了个功能比较强大的Button,下面附上代码

#ifndef _My_UTILS_H_
#define _My_UTILS_H_

#include "cocos2d.h"

namespace MyUtils
{
    bool IsTouchInside(cocos2d::Node* o, cocos2d::Vec2 const& p)
    {
        assert(o->getParent());
        auto siz = o->getContentSize();
        if (p.x < 0 || p.y < 0 || p.x >= siz.width || p.y >= siz.height)
            return false;
        return true;
    }

    bool IsTouchInside(cocos2d::Node* o, cocos2d::Touch* touch)
    {
        return IsTouchInside(o, o->convertTouchToNodeSpace(touch));
    }

    bool EnsureTouch(cocos2d::Node* o, cocos2d::Vec2 const& p)
    {
        //自己添加当button属于scrollview, ClippingRectangleNode等的子节点时的处理 
        if (!o->isVisible()) return false;
        auto n = o->getParent();
        CC_ASSERT(n);
        while (n)
        {
            if (!n->isVisible())
                return false;
            n = n->getParent();
        }
        return true;
    }
}

#endif




```



#ifndef __MY_BUTTON_H__
#define __MY_BUTTON_H__

#include "cocos2d.h"
using namespace cocos2d;


// Button 的 touch 事件
enum class ButtonEvents
{
    // 状态相关, x, y 没作用, lua 的话这两个参数也不会被压入
    Enabled,
    Disabled,
    // touch 相关: x, y 值为 touch 坐标( Button 内部坐标系 )
    TouchDown,
    TouchMoveInside,
    TouchMoveOutside,
    TouchMoveEnter,
    TouchMoveExit,
    TouchUpInside,
    TouchUpOutside,
    TouchCancel,
};

//  Button( 基于 Node ),ContentSize 为 touch 判定范围
struct MyButton : public cocos2d::Node
{
    // 当用于 scrollview 内时, swallow 须传 false( 可击穿 )
    static  MyButton* Create(bool swallow = true);
    static cocos2d::Node * create() = delete;
    typedef std::function EventHandlerType;
    EventHandlerType eventHandler;                          // 事件函数接口

    void Enable(bool v = true);
    void Swallow(bool v = true);
    bool IsEnabled() const;
    bool swallow = true;        // 吞吃标志( true: 不能击穿 )
protected:
    MyButton() : eventHandler(](MyButton* sender, ButtonEvents e, float x, float y) {}) {}
    cocos2d::EventListenerTouchOneByOne* touchListener = nullptr;   // Enable 时创建, Disable 时杀掉
    cocos2d::Touch* firstTouch = nullptr;                           // 记录第 1 次点击,用于吞噬非第 1 次点击

    bool inside = false;                                            // 手指当前是否位于 btn touch 区域内
};

#endif




```


#include "MyButton.h"
#include "MyUtiles.h"

using namespace cocos2d;

void MyButton::Enable(bool b)
{
    if (b)
    {
        if (touchListener) return;
        touchListener = EventListenerTouchOneByOne::create();
        touchListener->setSwallowTouches(swallow);
        touchListener->onTouchBegan = (Touch* t, Event* e)
        {
            if (firstTouch) return true;           // 如果已记录第 1 次点击,退出返回“已处理”( 吞掉 )
                                                   // 如果不在点击区域,或是任意一级 parent visible == false, 或是点在被裁剪的部分, 退出
            auto loc = this->convertTouchToNodeSpace(t);
            if (!MyUtils::IsTouchInside(this, loc) || !MyUtils::EnsureTouch(this, loc))
            {
                return false;
            }
            firstTouch = t;                         // 记录第1次点击
            inside = true;
            eventHandler(this, ButtonEvents::TouchDown, loc.x, loc.y);
            return true;
        };
        touchListener->onTouchMoved = (Touch* t, Event* e)
        {
            if (firstTouch != t) return;           // 如果不是第 1 次点击,直接退出
            auto loc = this->convertTouchToNodeSpace(t);
            if (MyUtils::IsTouchInside(this, loc) && MyUtils::EnsureTouch(this, loc))
            {
                if (!inside)
                {
                    inside = true;
                    eventHandler(this, ButtonEvents::TouchMoveEnter, loc.x, loc.y);
                }
                else
                {
                    eventHandler(this, ButtonEvents::TouchMoveInside, loc.x, loc.y);
                }
            }
            else
            {
                if (inside)
                {
                    inside = false;
                    eventHandler(this, ButtonEvents::TouchMoveExit, loc.x, loc.y);
                }
                else
                {
                    eventHandler(this, ButtonEvents::TouchMoveOutside, loc.x, loc.y);
                }
            }
        };
        touchListener->onTouchEnded = (Touch* t, Event* e)
        {
            if (firstTouch != t) return;           // 如果不是第 1 次点击,直接退出
            firstTouch = nullptr;                   // 清掉第 1 次点击的记录
            auto loc = this->convertTouchToNodeSpace(t);
            if (MyUtils::IsTouchInside(this, loc) && MyUtils::EnsureTouch(this, loc))
            {
                eventHandler(this, ButtonEvents::TouchUpInside, loc.x, loc.y);
            }
            else
            {
                eventHandler(this, ButtonEvents::TouchUpOutside, loc.x, loc.y);
            }
        };
        touchListener->onTouchCancelled = (Touch* t, Event* e)
        {
            auto loc = this->convertTouchToNodeSpace(t);
            eventHandler(this, ButtonEvents::TouchCancel, loc.x, loc.y);
        };
        Node::getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, this);
        eventHandler(this, ButtonEvents::Enabled, 0, 0);
    }
    else
    {
        if (touchListener == nullptr) return;
        Node::getEventDispatcher()->removeEventListener(touchListener);
        touchListener = nullptr;
        eventHandler(this, ButtonEvents::Disabled, 0, 0);
        firstTouch = nullptr;
    }
}

void MyButton::Swallow(bool v)
{
    if (swallow == v) return;
    swallow = v;
    if (touchListener)
    {
        touchListener->setSwallowTouches(v);
    }
}

MyButton* MyButton::Create(bool swallow)
{
    auto rtv = new MyButton();
    rtv->autorelease();
    rtv->swallow = swallow;
    rtv->Enable(true);                            // 初始化 touch 监听器
    return rtv;
}

bool MyButton::IsEnabled() const
{
    return touchListener != nullptr;
}



```

示例:

auto sp1 = Sprite::create(“CloseNormal.png”);
MyButton* mybutton = MyButton::Create();
sp1->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
sp1->setTag(1);
mybutton->addChild(sp1);
mybutton->setContentSize(Size(86, 86));
mybutton->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT);
mybutton->setPosition(100, 100);
mybutton->eventHandler = =](MyButton* sender, ButtonEvents e, float x, float y)
{
switch (e)
{
case ButtonEvents::Enabled:
{

    }
    break;
    case ButtonEvents::Disabled:
    {

    }
    break;
    case ButtonEvents::TouchDown:
    {
        sender->setScale(2);
    }
    break;
    case ButtonEvents::TouchMoveInside:
    {

    }
    break;
    case ButtonEvents::TouchMoveOutside:
    {

    }
    break;
    case ButtonEvents::TouchMoveEnter:
    {
        //sender->setScale(2);
    }
    break;
    case ButtonEvents::TouchMoveExit:
    {
        //sender->setScale(1);
    }
    break;
    case ButtonEvents::TouchUpInside:
    {
        sender->setScale(1);
    }
    break;
    case ButtonEvents::TouchUpOutside:
    {
        /*auto sp = sender->getChildByTag(1);
        sp->setVisible(false);*/
    }
    break;
    case ButtonEvents::TouchCancel:
    {

    }
    break;
    default:
        break;
    }
};

addChild(mybutton);

起码的介绍都没有就敢说功能强大,也是真敢吹

他这个应该是把按钮事件 分为双击事件 和 单击事件。

用法示例代码都贴出来了,自己水平低看不懂我也是没办法:14:

:14::14::14::14::14::14::14::14:

:2:感谢无私的奉献

楼主主要实现了哪些强大的功能?我在考虑要不要放到-x 里面去。

看我的示例代码,可以处理各种ButtonEvents的事件,在eventHander的lambda表达式中的switch…case中进行事件响应操作

这个就是多了个双击???完全不知道功能强大在哪里。。。。

— Begin quote from ____

引用第8楼2276450133于2015-08-18 10:20发表的 回 7楼(子龙山人) 的帖子 :
看我的示例代码,可以处理各种ButtonEvents的事件,在eventHander的lambda表达式中的switch…case中进行事件响应操作 http://www.cocoachina.com/bbs/job.php?action=topost&tid=319920&pid=1370554

— End quote

了解了,我考虑了一下是否有必要支持。

真以为我看不懂?我就呵呵了
分享代码是值得称赞,但是学别的策划一样吹牛就是无耻知道么

这种功能没比必要加进去,大部分人用不到

先不说强不强大 这代码风格和毕业生有一拼

:2: :2: :2: :2:

一看楼主就是写代码不喜欢写注释的。。。。