#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);
起码的介绍都没有就敢说功能强大,也是真敢吹
他这个应该是把按钮事件 分为双击事件 和 单击事件。
用法示例代码都贴出来了,自己水平低看不懂我也是没办法








感谢无私的奉献
楼主主要实现了哪些强大的功能?我在考虑要不要放到-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
了解了,我考虑了一下是否有必要支持。
真以为我看不懂?我就呵呵了
分享代码是值得称赞,但是学别的策划一样吹牛就是无耻知道么
这种功能没比必要加进去,大部分人用不到
先不说强不强大 这代码风格和毕业生有一拼

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