cocos2d-x 中 CCDirector::pause() 僅暫停調度器與動作,**觸摸分發器仍在運行**,導致彈窗、計費界面彈出時底層按鈕、菜單仍可觸發,極易造成誤操作與崩潰。
layer->setIsTouchEnabled(false); // 對每個 CCLayer/CCMenu 調用
缺陷:同一幀同一函數中先禁用後啟用會觸發斷言崩潰(分發器發現響應列表為空);管理多層狀態繁瑣,易遺漏。
創建一個透明 CCLayer,註冊為**最高優先級、吞噬觸摸**的目標型代理,覆蓋在當前場景最上層。
class NoTouchLayer : public CCLayer {
public:
LAYER_NODE_FUNC(NoTouchLayer);
virtual bool init();
virtual void registerWithTouchDispatcher();
virtual bool ccTouchBegan(CCTouch* pTouch, CCEvent* pEvent);
virtual void ccTouchMoved(CCTouch* pTouch, CCEvent* pEvent);
virtual void ccTouchEnded(CCTouch* pTouch, CCEvent* pEvent);
};
bool NoTouchLayer::init() {
if (!CCLayer::init()) return false;
setIsTouchEnabled(true);
return true;
}
void NoTouchLayer::registerWithTouchDispatcher() {
// INT_MIN 為最高優先級,true 表示吞噬事件不再向下分發
CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, INT_MIN, true);
CCLayer::registerWithTouchDispatcher();
}
bool NoTouchLayer::ccTouchBegan(CCTouch* pTouch, CCEvent* pEvent) { return true; }
void NoTouchLayer::ccTouchMoved(CCTouch* pTouch, CCEvent* pEvent) {}
void NoTouchLayer::ccTouchEnded(CCTouch* pTouch, CCEvent* pEvent) {}
// 彈窗彈出時
NoTouchLayer* shield = NoTouchLayer::create();
scene->addChild(shield, INT_MAX); // 極大 Z 值確保最上層
// 彈窗關閉時
shield->removeFromParentAndCleanup(true);