在新手引导的过程中,我们往往会强制用户执行指定区域的操作。那么一般的操作我们是在原有的界面上增加一个遮罩层,指定区域内可以向下传递touch事件。而其他区域则吸收掉点击事件。在cocos2d-x 3.x中的简单实现方式如下。
1.首先我们创建一个主要界面,里面有一些菜单按钮
主要内容代码如下:
void MainLayer::initView()//初始化显示的方法
{
log("init MainLayer view");
std::vector<std::string> vec;
vec.push_back("开始");
vec.push_back("介绍");
vec.push_back("退出");
int i = 0;
double startX = VisibleRect::center().x;
double startY = VisibleRect::center().y + 100;
for (auto& title : vec)
{
//这里只是简单放三个按钮。standardButtonWithTitle是自己实现的初始化ControlButton
ControlButton *button = standardButtonWithTitle(title.c_str());
//button->setAdjustBackgroundImage(false);
button->setPosition(Point (startX,startY- button->getContentSize().height / 2));
button->getBackgroundSpriteForState(Control::State::NORMAL)->setColor(Color3B(0,255,0));
button->getBackgroundSpriteForState(Control::State::HIGH_LIGHTED)->setColor(Color3B(0,255,0));
addChild(button);
button->setTag(i);
button->addTargetWithActionForControlEvents(this, cccontrol_selector(LoginLayer::touchUpInsideAction), Control::EventType::TOUCH_UP_INSIDE);
startY -= (button->getContentSize().height + 30);
++i;
}
auto listener1 = EventListenerTouchOneByOne::create();
//swallow是吞咽的意思. 代表本layer会吸收掉touch事件不向下层layer传递
listener1->setSwallowTouches(true);
listener1->onTouchBegan = [](Touch* touch, Event* event){
return true;
};
listener1->onTouchBegan = CC_CALLBACK_2(LoginLayer::layerTouch, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
}
2.然后我们增加一个新的YinDaoLayer 它放在MainLayer的parent(为一个Scene)中,z值大于MainLayer.这里也是设计的一个方面,所有的Layer都放在同一个scene中,并进行统一管理
void YinDaoLayer::initView()//初始化显示的方法
{
log("init YinDaoLayer view");
//引导界面上可以点击的一个图片,设定它的意义只是为了能够向下传递touch事件
auto pSprite = CCSprite::create("qiyu.png");
pSprite->setPosition(VisibleRect::center() + Point(rand()%100,50));
pSprite->setTag(100);
addChild(pSprite);
//layer的按键监听事件,一样设置为吸收向下传递事件
auto listener1 = EventListenerTouchOneByOne::create();
listener1->setSwallowTouches(true);
listener1->onTouchBegan = [=](Touch* touch, Event* event){
Point locationInNode = pSprite->convertToNodeSpace(touch->getLocation());
Size s = pSprite->getContentSize();
Rect rect = Rect(0, 0, s.width, s.height);
//这里是重点
//我们设定在点击到图片的区域的时候本层不做事件处理.因为return true.则本层会做事件吸收,不会向下传递了
if (rect.containsPoint(locationInNode)) {
return false;
}
return true;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
//设置sprite的touch事件
auto listener2 = EventListenerTouchOneByOne::create();
//注意 它并没有吞咽touch事件 代表点击这个按钮的时候可以向下传递事件
listener2->onTouchBegan = [](Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
//Get the position of the current point relative to the button
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
Size s = target->getContentSize();
Rect rect = Rect(0, 0, s.width, s.height);
//Check the click area
//点击区域在图片区域内时 代表可以执行图片的touch事件。
if (rect.containsPoint(locationInNode))
{
log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
target->setOpacity(180);
return true;
}
return false;
};
listener2->onTouchEnded = [=](Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
log("sprite onTouchesEnded.. ");
target->setOpacity(255);
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
Size s = target->getContentSize();
Rect rect = Rect(0, 0, s.width, s.height);
//Check the click area
if (rect.containsPoint(locationInNode))
{
//执行图片按下去后的操作
}
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener2, pSprite);
}