【cocos2d-x3.2游戏开发】 模态对话框拦截所有事件

来源:互联网 发布:中国重工业 知乎 编辑:程序博客网 时间:2024/06/05 20:56

开发基础:Cocos2dx 3.2

开发目标:1.实现模态对话框,无论弹出多少层都可以拦截事件。 2.ScrollView上有按钮,可以点击按钮滑动,响应事件并且不影响模态对话框的事件拦截。



实现方法:
1.Cocos2dx 2版本中,我们会设置DlgLayer事件的优先级为-128,这样会拦截底层的按钮事件(-128),但是问题是会拦截当前层的按钮事件(-128),需要将DlgLayer上的点击事件手动传入对话框上的按钮处理。
3.0版本中已经不再使用了,这种方法有很大的局限性,尤其在界面比较多,比较复杂的情况下,传递事件是一种比较挫的做法。直接排除。

2.Cocos2dx 3.X版本中,因为改变了事件的规则,几乎所有的控件的事件处理都按SceneGraphPriority走的,甚至连Cocos2dx 2.X版本的Menu的-128也更改为0了。
做法: 直接弹出一个DlgLayer(CCColorLayer), 封装一个事件吞噬(onTouchBegan, onTouchEnded...), 事件优先级为addEventListenerWithSceneGraphPriority,即0
 因为所有层的拦截事件优先级为0,就会先处理最上方的事件,即弹出的对话框事件。


特殊情况:
弹出的对话框上有ScrollView,ScrollView上有按钮,最常见的问题就是
1.点击按钮能触发事件,但是点击按钮无法滑动ScrollView
  解决办法:把按钮优先级设置为1(当前ScrollView的优先级为0),这样就能点着按钮滑动了。
  但是产生新问题,按钮能滑动,却不能点击了,因为DlgLayer的优先级为0,会拦截掉按钮的事件。

2.有一个特殊的API,setSwallowTouches,在为一个控件封装点击事件的时候,可以将setSwallowTouches(false)。
这就意味着按钮能够响应点击事件,但是因为没有吞噬事件,就可以把按钮的事件传给ScrollView,ScrollView也可以滑动。
DlgLayer 优先级 0
ScrollView 优先级 0
Button 优先级 0
根据ZOrder的顺序,先触发Button,然后是ScrollView,最后是DlgLayer

3. 3.0版本不建议修改priority,因为你无法得知需要弹出多少层对话框,就无法确定每个对话框的priority

eventdispatcher事件分发规则
添加监听的方法addEventListenerWithSceneGraphPriority和addEventListenerWithFixedPriority

1.SceneGraphPriority
和Node节点绑定的所有事件的优先级为0,
添加监听器后,事件监听列表内部的排序为 "<0, scene graph (0 priority), >0"

2.FixedPriority
用来自己定制优先级,一般设置"<0 或 >0"

3. 响应事件的优先级,数值越小,越先响应,-1 0 1这个顺序
内部事件处理顺序:
1.优先级为负数的事件
2.优先级为0(scene graph)的事件,相同的优先级会根据Node的z顺序高的(绘制于顶部的)节点将优于z顺序低的节点。这将保证了诸如触碰事件的自顶向下传播。
3.优先级为整数的事件


最后附带一个lua版封装的TouchableSprite

一个可点击的图片,可以在ScrollView上点击滑动,响应事件。


[cpp] view plaincopy
  1. --[[  
  2.     可点击的图片,可以设置响应的优先级。  
  3.     比如ScrollView上的按钮,可以用TouchableSprite实现。将TouchableSprite设置为不吞噬消息即可。  
  4.       
  5.     ~~~lua  
  6.   
  7.     -- 点击点击事件  
  8.     local function equip_touch_began_listener(sender, touch, event)  
  9.     end  
  10.   
  11.     -- 点击结束事件  
  12.     local function equip_touch_ended_listener(sender, touch, event)  
  13.         if scroll_view:isTouchMoved() then  
  14.             return  
  15.         end  
  16.           
  17.         -- 可以添加容错点击,如5个像素内。  
  18.         local start_pt = touch:getStartLocation()  
  19.         local end_pt = touch:getLocation()  
  20.         if checkint(start_pt.x) == checkint(end_pt.x) and checkint(start_pt.y) == checkint(end_pt.y) then  
  21.             print(sender.id_)  
  22.             print("Ready to equip......")  
  23.         end  
  24.     end  
  25.   
  26.     -- 添加到ScrollView上可点击的图片  
  27.     local sp = TouchableSprite.new("data/equip.png",   
  28.                                     equip_touch_began_listener,  
  29.                                     equip_touch_ended_listener,  
  30.                                     false)  
  31.   
  32.     sp.id_ = 9999  
  33.     scroll_view:addChild(sp)  
  34.   
  35.     ~~~lua  
  36.   
  37. ]]  
  38. local TouchableSprite = class("TouchableSprite", function(pic_path)  
  39.         return display.newSprite(pic_path)  
  40.     end)  
  41.   
  42. TouchableSprite.__index = TouchableSprite  
  43. TouchableSprite.listener_ = nil  
  44. TouchableSprite.swallowTouch_ = true  
  45. TouchableSprite.fixedPriority_ = 0  
  46. TouchableSprite.useNodePriority_ = false  
  47. TouchableSprite.removeListenerOnTouchEnded_ = false  
  48. TouchableSprite.touch_began_listener_ = nil  
  49. TouchableSprite.touch_ended_listener_ = nil  
  50.   
  51. --[[  
  52. 构造一个可响应点击事件的TouchableSprite。  
  53.   
  54. ~~~lua  
  55.       
  56.     -- 监听器有三个参数,第一个参数是自己  
  57.     local function touch_began_listener(sender, touch, event)  
  58.     end  
  59.   
  60.     local function touch_ended_listener(sender, touch, event)  
  61.         local start_pt = touch:getStartLocation()  
  62.         local end_pt = touch:getLocation()  
  63.         if checkint(start_pt.x) == checkint(end_pt.x) and checkint(start_pt.y) == checkint(end_pt.y) then  
  64.             print(sender.id_)  
  65.             print("Ready to equip......")  
  66.         end  
  67.     end  
  68.   
  69.     local sp = TouchableSprite.new("data/equip.png",   
  70.             equip_touch_began_listener,  
  71.             equip_touch_ended_listener)  
  72.   
  73.     sp:setTexture("data/equip1.png")  
  74.     sp:setPriority(1)  
  75.     parent:addChild(sp)  
  76.       
  77. ~~~lua  
  78.   
  79. @param string pic_path 传入图片路径.可为空,后通过:setTexture("pic_path")重新设置  
  80. @param touch_began_listener 点击开始事件的监听器。为空时不响应。 监听器有三个参数,第一个参数是可点击图片自己  
  81. @param touch_ended_listener 点击结束时事件监听器。为空时不响应。 监听器有三个参数,第一个参数是可点击图片自己  
  82. @param swallow_touch 是否吞噬事件 true 事件不再向下传递 false 响应完事件后,继续向下传递  
  83. ]]  
  84. function TouchableSprite:ctor(pic_path, touch_began_listener, touch_ended_listener, swallow_touch)  
  85.     self.touch_began_listener_ = touch_began_listener  
  86.     self.touch_ended_listener_ = touch_ended_listener  
  87.     self.swallowTouch_ = swallow_touch  
  88.   
  89.      local function onNodeEvent(event)  
  90.         if event == "enter" then  
  91.             self:onEnter()  
  92.         elseif event == "exit" then  
  93.             self:onExit()  
  94.         end  
  95.     end  
  96.       
  97.     self:registerScriptHandler(onNodeEvent)  
  98. end  
  99.   
  100. function TouchableSprite:setTouchBeganListener(touch_began_listener)  
  101.     self.touch_began_listener_ = touch_began_listener  
  102. end  
  103.   
  104. function TouchableSprite:setTouchEndedListener(touch_ended_listener)  
  105.     self.touch_ended_listener_ = touch_ended_listener  
  106. end  
  107.   
  108. function TouchableSprite:onEnter()  
  109.     local eventDispatcher = self:getEventDispatcher()  
  110.   
  111.     local function onTouchBegan(touch, event)  
  112.         local locationInNode = self:convertToNodeSpace(touch:getLocation())  
  113.         local s = self:getContentSize()  
  114.         local rect = cc.rect(0, 0, s.width, s.height)  
  115.               
  116.         if cc.rectContainsPoint(rect, locationInNode) then  
  117.   
  118.             if self.touch_began_listener_ then  
  119.                 self:touch_began_listener_(self,touch, event)  
  120.             end  
  121.             return true  
  122.         end  
  123.   
  124.         return false      
  125.     end  
  126.   
  127.     local function onTouchMoved(touch, event)  
  128.           
  129.     end  
  130.   
  131.     local  function onTouchEnded(touch, event)  
  132.         print("onTouchEnded.......")  
  133.         if self.touch_ended_listener_ then  
  134.             self:touch_ended_listener_(self, touch, event)  
  135.         end  
  136.   
  137.         if self.removeListenerOnTouchEnded_ then  
  138.             eventDispatcher:removeEventListener(self.listener_)  
  139.         end  
  140.     end  
  141.   
  142.     local listener = cc.EventListenerTouchOneByOne:create()  
  143.     self.listener_ = listener  
  144.     listener:setSwallowTouches(self.swallowTouch_)  
  145.       
  146.     listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN )  
  147.     listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED )  
  148.     listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED )  
  149.   
  150.     if 0 == self.fixedPriority_ then  
  151.         eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self)  
  152.     else  
  153.         eventDispatcher:addEventListenerWithFixedPriority(listener,self.fixedPriority_)  
  154.     end  
  155. end  
  156.   
  157. function TouchableSprite:setSwalllowTouch(swallow)  
  158.     self.swallowTouch_ = swallow  
  159. end  
  160.   
  161. function TouchableSprite:onExit()  
  162.     local eventDispatcher = self:getEventDispatcher()  
  163.     eventDispatcher:removeEventListener(self.listener_)  
  164. end  
  165.   
  166. function TouchableSprite:setPriority(fixedPriority)  
  167.     self.fixedPriority_ = fixedPriority  
  168.     self.useNodePriority_ = false  
  169. end  
  170.   
  171. function TouchableSprite:removeListenerOnTouchEnded(toRemove)  
  172.     self.removeListenerOnTouchEnded_ = toRemove  
  173. end  
  174.   
  175. function TouchableSprite:setPriorityWithNode(useNodePriority)  
  176.     self.fixedPriority_ = 0  
  177.     self.useNodePriority_ = useNodePriority  
  178. end  
  179.   
  180. return TouchableSprite 
原文请看:http://blog.csdn.net/teng_ontheway/article/details/39528037
0 0