触摸事件的重新分发(当弹出一个新窗口时,如何屏蔽掉下面层的触摸事件)

来源:互联网 发布:知来者之可追古今异义 编辑:程序博客网 时间:2024/05/12 14:54
前段时候换工作时,去触控科技面试,面试官问了这么一个问题。”当弹出一个新窗口时,如果屏蔽掉下面层的触摸事件?“
这个问题对于接触cocos2d引擎一段时间的同学来说,都不算难。当时我想到了两种解决方案,也是在之前项目中用到过的:


一、加一个屏蔽层,TouchMaskLayer, 它的写法差不多就是 
a. CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuTouchPriority, true);
b. ccTouchBegan 中 return true;
二、先把本层的触摸开关手动关掉,再加弹出层,实现方式差不多是 :
a. 本层实现 onControl() 和 lostControl(), 把本层触摸相关的对象(CCLayer, CCMenu CCEditbox,...)setTouchEnable(true/false), 
b.弹出新层之前,调用lostControl(), 新层关掉时回调onControl()


第一种写法简单粗暴,简单的逻辑可以直接这么用。它的问题是,如果弹出层上需要多点触摸的话,这是行不通的,因为多点触摸优先级没有TouchMaskLayer高,它将得不到事件。
第二种方法,是和三国塔防程序同事杨新宁,魏莱一起讨论而来的。这种方式我一直在用,除了麻烦一些外,没发现任何问题。其实这种方式也没想象中的麻烦,因为一个场景中可以有触摸事件的对象也就那几个。


我问他们有什么更好的方式时,捕鱼2主程汪东林(在些表示感谢)说了他们的做法,自己处理事件分发。我根据这个想法自己做了个弹出层的基类UpperLayer


[cpp] view plaincopyprint?
  1. //  
  2. //  UpperLayer.h  
  3. //  MythLeague  
  4. //  
  5. //  Created by raochongtao on 13-6-26.  
  6. //  
  7. //  
  8.   
  9. /* 功能 
  10.  * 1. 弹出层的基类, 比下层拥有更高的优先级, 用于屏蔽下层,及本层外触摸事件 
  11.  * 2. 提供一个容量,及相应方法,用于装纳需要处理事件的对象 CCTouchDelegate*对象,  
  12.  */  
  13.   
  14.   
  15. #ifndef __MythLeague__UpperLayer__  
  16. #define __MythLeague__UpperLayer__  
  17.   
  18. #include "Global/Constants.h"  
  19. #include "CommonLayer/TouchLogicLayer.h"  
  20.   
  21. class UpperLayer : public  TouchLogicLayer{  
  22.       
  23. public:  
  24.     UpperLayer();  
  25.     virtual ~UpperLayer();  
  26.       
  27.     bool init();  
  28.           
  29.     void onEnter();  
  30.     void onExit();  
  31.     void registerWithTouchDispatcher();  
  32.       
  33.     void appendToTouchDispatch(cocos2d::CCTouchDelegate* p_touchableObject);  
  34.       
  35. #pragma mark 触摸相关  
  36.     //开始  
  37.     bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);  
  38.       
  39.     //移动  
  40.     void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);  
  41.       
  42.     //结束  
  43.     void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);  
  44.       
  45.     //点击home键或其它方式引起的取消  
  46.     void ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);  
  47.       
  48.       
  49. public:  
  50.     //cocos2d::CCArray* m_touchDispatchTable;  
  51.     std::vector<cocos2d::CCTouchDelegate*> m_touchDispatchTable;  
  52.     int m_iIndex;//m_iIndex-1为实际索引  
  53. };  
  54.   
  55. #endif /* defined(__MythLeague__UpperLayer__) */  

[cpp] view plaincopyprint?
  1. //  
  2. //  UpperLayer.cpp  
  3. //  MythLeague  
  4. //  
  5. //  Created by raochongtao on 13-6-26.  
  6. //  
  7. //  
  8.   
  9. #include "UpperLayer.h"  
  10.   
  11. using namespace cocos2d;  
  12.   
  13. UpperLayer::UpperLayer(){  
  14.       
  15. }  
  16. UpperLayer::~UpperLayer(){  
  17.       
  18.       
  19. }  
  20.   
  21. bool UpperLayer::init(){  
  22.     bool l_bResult = true;  
  23.     do {  
  24.         if(!TouchLogicLayer::init()){  
  25.             l_bResult = false;  
  26.         }                  
  27.           
  28.     } while (0);  
  29.     return l_bResult;  
  30. }  
  31.   
  32. void UpperLayer::onEnter(){  
  33.     TouchLogicLayer::onEnter();  
  34. }  
  35. void UpperLayer::onExit(){  
  36.     TouchLogicLayer::onExit();  
  37. }  
  38.   
  39. void UpperLayer::registerWithTouchDispatcher()  
  40. {  
  41.     cocos2d::CCDirector* pDirector = cocos2d::CCDirector::sharedDirector();  
  42.     pDirector->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuHandlerPriority-1, true);  
  43. }  
  44.   
  45. void UpperLayer::appendToTouchDispatch(CCTouchDelegate* p_touchableObject){  
  46.     //断言,p_touchableLayer是CCLayer*类型, (可以是继承)  
  47.     CCAssert(dynamic_cast<CCTouchDelegate*>(p_touchableObject) != NULL, "p_touchableLayer must be a layer");  
  48.     m_touchDispatchTable.push_back(p_touchableObject);  
  49. }  
  50.   
  51. #pragma mark 触摸相关  
  52. //开始  
  53. bool UpperLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){  
  54.     //super  
  55.     TouchLogicLayer::ccTouchBegan(pTouch, pEvent);  
  56.       
  57.     m_iIndex = Common_Empty;  
  58.     CCTouchDelegate* l_touchAble = NULL;  
  59.     int l_iIndex = 0;  
  60.     for (; l_iIndex<m_touchDispatchTable.size(); l_iIndex++) {  
  61.         l_touchAble = m_touchDispatchTable[l_iIndex];  
  62.         if (l_touchAble && l_touchAble->ccTouchBegan(pTouch, pEvent))  
  63.         {  
  64.             m_iIndex = l_iIndex;  
  65.             break;  
  66.         }  
  67.     }      
  68.     return true;  
  69. }  
  70.   
  71. //移动  
  72. void UpperLayer::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){  
  73.     //super  
  74.     TouchLogicLayer::ccTouchMoved(pTouch, pEvent);  
  75.       
  76.     if (m_iIndex >= 0) {  
  77.         CCTouchDelegate* l_touchAble = m_touchDispatchTable[m_iIndex];  
  78.         l_touchAble->ccTouchMoved(pTouch, pEvent);  
  79.     }  
  80. }  
  81.   
  82. //结束  
  83. void UpperLayer::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){  
  84.     //super  
  85.     TouchLogicLayer::ccTouchEnded(pTouch, pEvent);  
  86.       
  87.     if (m_iIndex >= 0) {  
  88.         CCTouchDelegate* l_touchAbleLayer = m_touchDispatchTable[m_iIndex];  
  89.         l_touchAbleLayer->ccTouchEnded(pTouch, pEvent);  
  90.     }  
  91. }  
  92.   
  93. //点击home键或其它方式引起的取消  
  94. void UpperLayer::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){  
  95.       
  96. }  

所有的弹出层,只要继承一下这个就可以,他的优点是事件分发由自己来控制,比较灵活
原创粉丝点击