码迷,mamicode.com
首页 > 其他好文 > 详细

关于cocostudio动态添加控件触摸响应无效的学习

时间:2015-04-20 01:47:34      阅读:1883      评论:0      收藏:0      [点我收藏+]

标签:

time:2015/04/19

1. 描述

  * 自己也碰到了在cocostudio上碰到点击按钮没有响应的情况

  * 另外,网上有朋友也碰到过,所以自己觉得按照3.0的cocos引擎的新渲染逻辑应该是可以设置的

2. 学习

(1)代码直接调试

动态添加一个按钮或者一个精灵到有cocostudio加载的layout

* 按钮和layout在一个层级,都加载layer上,没有位置上的重叠:结果没有影响,两遍都能响应触摸事件

* 按钮和layout在一个层级,都加载layer上,有位置上的重叠:结果依旧没有影响

* 按钮在layout之前addchild:直接看不见了

* 按钮在layout之后addchild:没有影响

* 按钮属于layout,layout:addChild(),没有位置上的重叠:结果没有影响

* 按钮属于layout,layout:addChild(),有位置上的重叠:结果没有影响

* 添加一个精灵,自己添加触摸事件:

Sprite* sprite = Sprite::create("cocosui/green_edit.png");
bgd->addChild(sprite, 0);
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = CC_CALLBACK_2(UIButtonTest_Editor::onTouchBegan, this);
listener->onTouchEnded = CC_CALLBACK_2(UIButtonTest_Editor::onTouchEnded, this);
 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

  1)localZorder默认为0

    * 有影响,具体表现为:点击layout上的按钮有响应;点击精灵sprite也有响应;点击除了layout上的按钮之外所有的地方,包括layout内以及外的点都会响应sprite

    * 为什么?因为默认的Button做了区域检测,点击按钮之外不响应;但是自己上面定义的精灵没有做处理,所以原则上会接受到任何触摸的消息

    * 点击layout上的按钮的时候,sprite其实是没有接受到触摸消息的,说明什么?第一,layout上的按钮把消息吞掉了;第二,layout上的按钮先于sprite接受到触摸消息

  -->关于说明的第一点,看源码: [_touchListener->setSwallowTouches(true);]

void Widget::setTouchEnabled(bool enable)
{
    if (enable == _touchEnabled)
    {
        return;
    }
    _touchEnabled = enable;
    if (_touchEnabled)
    {
        _touchListener = EventListenerTouchOneByOne::create();
        CC_SAFE_RETAIN(_touchListener);
        _touchListener->setSwallowTouches(true);
        _touchListener->onTouchBegan = CC_CALLBACK_2(Widget::onTouchBegan, this);
        _touchListener->onTouchMoved = CC_CALLBACK_2(Widget::onTouchMoved, this);
        _touchListener->onTouchEnded = CC_CALLBACK_2(Widget::onTouchEnded, this);
        _touchListener->onTouchCancelled = CC_CALLBACK_2(Widget::onTouchCancelled, this);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(_touchListener, this);
    }
    else
    {
        _eventDispatcher->removeEventListener(_touchListener);
        CC_SAFE_RELEASE_NULL(_touchListener);
    }
}

  -->关于第二点看后面的分享-->

  2)localZorder为1,bgd->addChild(sprite, 1)

    * 同1)

  3)sprite的localZOrder为-1

    * 同1)

  4)sprite->setGlobalZorder(1)

    * 同1)

 

(2)cocos的事件处理顺序

* 看两个接口大致可以看到,处理顺序有优先级之分: <0, 0, >0

addEventListenerWithSceneGraphPriority: 默认为0
addEventListenerWithFixedPriority: 有正负之分了

* 优先级判断的逻辑

void EventDispatcher::sortEventListeners(const EventListener::ListenerID& listenerID)
{
    DirtyFlag dirtyFlag = DirtyFlag::NONE;
    
    auto dirtyIter = _priorityDirtyFlagMap.find(listenerID);
    if (dirtyIter != _priorityDirtyFlagMap.end())
    {
        dirtyFlag = dirtyIter->second;
    }
    
    if (dirtyFlag != DirtyFlag::NONE)
    {
        // Clear the dirty flag first, if `rootNode` is nullptr, then set its dirty flag of scene graph priority
        dirtyIter->second = DirtyFlag::NONE;

        if ((int)dirtyFlag & (int)DirtyFlag::FIXED_PRIORITY)
        {
       //自定义优先级排序 sortEventListenersOfFixedPriority(listenerID); }
if ((int)dirtyFlag & (int)DirtyFlag::SCENE_GRAPH_PRIORITY) { auto rootNode = Director::getInstance()->getRunningScene(); if (rootNode) {
          //默认优先级为0的排序 sortEventListenersOfSceneGraphPriority(listenerID, rootNode); }
else { dirtyIter->second = DirtyFlag::SCENE_GRAPH_PRIORITY; } } } }

  -->自定义优先级没什么好说的,看排序算法就知道了,按自定义的数值排序;

  -->如果相同就按照开始插入的顺序继续,排序算法是不是稳定的还要再看

* 默认为0的优先级排序

visitTarget(rootNode, true);
    
    // After sort: priority < 0, > 0
    std::sort(sceneGraphListeners->begin(), sceneGraphListeners->end(), [this](const EventListener* l1, const EventListener* l2) {
        return _nodePriorityMap[l1->getAssociatedNode()] > _nodePriorityMap[l2->getAssociatedNode()];
    });

  -->这里的排序算法已经不同于自定义的排序算法了,一眼看上去不明觉厉

  -->所以要看上面的一个函数,visitTarget,就是这个函数中构造_nodePriorityMap结构的

  -->仔细看visitTarget函数其实就是cocos3.0以上的一个渲染顺序的逻辑:globalZorder和globalZorder两个共同决定了渲染顺序,globalZorder高于localZorder,这同时也决定了这个渲染顺序可以让不同的layer上的node有不同的渲染顺序,而且跟parent的layer层级关系没有关系(是这样理解的,但是没有去验证!)  

  -->总结就是:这里的优先级是先看节点的globalZorder,再看localZorder,如果相同就按照默认加入的顺序。即,先加入的先渲染,先处理事件

3. 问题

  从上面的理解来看,cocostudio的按钮在最底层,所以会先接受到触摸消息,并且吞掉,从而其他控件(自定义的)不能接受到触摸消息;但是,自己即使设置了自定义的sprite,还是在studio的按钮之后接收到触摸消息,结果是如果点击的是按钮,自定义控件不会响应!

 

4. 参考:

[1] http://www.it165.net/pro/html/201405/13283.html

关于cocostudio动态添加控件触摸响应无效的学习

标签:

原文地址:http://www.cnblogs.com/pk-run/p/4440494.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!