多Layer觸摸傳遞問題

 遇到情況 :
場景a -》層1-》層2
1、層一點擊沒有傳遞到場景a   (這個考慮到可能是場景調用的層 內部代碼屏幕場景中的點擊  如果層調用層就出現2情況了
2、但    層2點擊會點擊到層1
處理方式:
爲層創建全局觸摸調用函數  touchbegan 返回true 吞噬事件 繼續調用touchmove等
.h
bool onTouchBegan(Touch* touch, Event* event) ;
void onTouchMoved(Touch* touch, Event* event);
void onTouchEnded(Touch* touch, Event* event) ;

 

.cpp
EventListenerTouchOneByOne*touchListener = EventListenerTouchOneByOne::create();//給scrollview所有sprite添加監聽用
touchListener->onTouchBegan = CC_CALLBACK_2(WjjnLayer::onTouchBegan, this);
touchListener->onTouchMoved = CC_CALLBACK_2(WjjnLayer::onTouchMoved, this);
touchListener->onTouchEnded = CC_CALLBACK_2(WjjnLayer::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
touchListener->setSwallowTouches(true);

bool WjjnLayer::onTouchBegan(Touch* touch, Event* event) { return true; }
void WjjnLayer::onTouchMoved(Touch* touch, Event* event) { }
void WjjnLayer::onTouchEnded(Touch* touch, Event* event) { } 


具體實現中  先加入以上,在加入stduio中編輯的控件button的相關代碼 加入觸摸序列  是按鈕優先級大於上面的優先級


如何讓自定義Layer觸發觸摸事件?

複製代碼
bool LayerXXX::init(){  
 
this->setTouchEnabled(true);  
CCTouchDispatcher
* td = CCDirector::sharedDirector()->getTouchDispatcher();  
td
->addTargetedDelegate(this0true); //kCCMenuHandlerPriority - 10  // ...}
複製代碼

CCTouchDispatcher是管理cocos2d-x中所有Touch事件派發的類,

CCTouchDispatcher中包含了兩個CCTouchHandler的列表,
分別存儲StandardTouchHandler和 TargetedTouchHandler。

屬性:
this->mTouchPriporty

Layer 優先級越小越高
越低越先響應事件

實驗一:當兩個Layer優先級同等的時候會怎麼樣呢?

實驗發現,同等優先級下,後添加的Layer先響應事件。

複製代碼
//-------------------------------//Touch1 100//Touch2 100
 
Touch1Layer* touch1layer = Touch1Layer::create( ccc4f(255,0,0,128), 100100 );
 
this->addChild( touch1layer );
touch1layer
->setPosition(200100);
Touch2Layer
* touch2layer = Touch2Layer::create( ccc4f(255,255,0,128), 100100 );
 
this->addChild( touch2layer );
touch2layer
->setPosition(250100);
 
//結果://Touch2//Touch1//-------------------------------//Touch1 100//Touch2 100
 
Touch2Layer* touch2layer = Touch2Layer::create( ccc4f(255,255,0,128), 100100 );
 
this->addChild( touch2layer );
touch2layer
->setPosition(250100);
Touch1Layer
* touch1layer = Touch1Layer::create( ccc4f(255,0,0,128), 100100 );
 
this->addChild( touch1layer );
touch1layer
->setPosition(200100);
//結果:Touch1Touch2
-------------------------------
Touch1 100
 
Touch2 99
 
Touch2Layer* touch2layer = Touch2Layer::create( ccc4f(255,255,0,128), 100100 );
 
this->addChild( touch2layer );
touch2layer
->setPosition(250100);
Touch1Layer
* touch1layer = Touch1Layer::create( ccc4f(255,0,0,128), 100100 );
 
this->addChild( touch1layer );
touch1layer
->setPosition(200100);
 
//結果://Touch2//Touch1//說明優先級越小越先觸發事件//-------------------------------
複製代碼

如何阻塞事件的向後傳遞?

原理:
mSwallowsTouches = false的時候,該層的touch事件若接受處理後,touch事件穿透,進入下個註冊touch事件的layer進行處理

若mSwallowsTouches = true時,當該層處理touch事件的時候,若bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
return true時候,則touch事件被該層接收走,其他優先級較低的,就不會接收到touch事件的處理申請了。

關於ccTouchBegan的返回值
true:
本層的後續Touch事件可以被觸發,並阻擋向後層傳遞
false:
本層的後續Touch事件不能被觸發,並向後傳遞

總結:

如何阻塞事件的向後傳遞?

主要是利用了TargetedTouchDelegate 的一個叫SwallowTouch的參數 ,如果這個開關打開的話,

比他權限低的handler 是收不到 觸摸響應的,這裏的權限低的意思是先看priority(priority越低的優先級越高)再看哪個Layer最後addChild進去(越後添加的優先級越高)。

CCMenu 就是開了Swallow 並且權限爲-128(權限是越小越好),所以CCMenu的事件不會出現擊穿

mSwallowsTouches = true 並且 ccTouchBegan 返回 true

如何讓Layer所有觸摸同時穿透Begin、Move、End事件?

mSwallowsTouches = false 並且 ccTouchBegan 返回 true

ccTouchBegan 返回 true 表示同層處理後續事件(吞噬)
ccTouchBegan 返回 false 表示同層不處理後續事件(Move End Cancled)  (擊穿)

mSwallowsTouches 設爲 true 表示觸摸不向下層傳遞(不一定 如mSwallowsTouches爲true began返回false還是會向後傳遞)
mSwallowsTouches 設爲 false 表示觸摸向下層傳遞(不知有啥用)

this->mTouchPriporty 越小,越先接收到觸摸

this->mTouchPriporty 同等,越後addChild的越先響應

如何管理多個對話框的優先級?

事件的優先級和繪圖的優先級的關係和區別?

VertexZ 又是什麼?(VertexZ是openGl的z軸)


繪圖的優先級叫ZOrder

如何改版繪圖的優先級?

如在容器中通過調用
this->reorderChild(CCNode* child, int zOrder);

如何設置觸摸事件的優先級?
CCTouchDispatcher::sharedDispatcher()->setPriority(kCCMenuTouchPriority - 1, layer);

如何得到觸摸事件的優先級?
this->mTouchPriporty (CCNode類成員 私有變量)

如何遍歷容器獲取特定的對象??

void Touch1Layer::setFocus()
{
// zorder=1;  priority= kCCMenuTouchPriority - 2;
// zorder
SceneController::GetInstancePtr()->getCurLayer()->reorderChild(this, 1);
// 
CCTouchDispatcher::sharedDispatcher()->setPriority(kCCMenuTouchPriority - 2, this);
}
void Touch1Layer::loseAllFocus()
{
// 
CCArray* arrChilds = SceneController::GetInstancePtr()->getCurLayer()->getChildren();
for(int i=0; i< arrChilds->count(); i++)
{
CCLayerColor* layer = dynamic_cast< CCLayerColor* >( arrChilds->objectAtIndex(i) );
// ()
if(layer != NULL && layer != this)
{
// zorder=0;  priority= kCCMenuTouchPriority - 1;
SceneController::GetInstancePtr()->getCurLayer()->reorderChild(layer, 0);
CCTouchDispatcher::sharedDispatcher()->setPriority(kCCMenuTouchPriority - 1, layer);
}
}
}
 

如何判斷點在矩形內部?

 
CCPoint pos = this->getPosition();
CCSize size = this->getContentSize();
CCRect rect(pos.x, pos.y, size.width, size.height);
if( CCRect::CCRectContainsPoint(rect, point)  )
{
}
 


z值大的成員在z值小的成員的上面;

官方解釋:

Differences between openGL Z vertex and cocos2d Z order:
   - OpenGL Z modifies the Z vertex, and not the Z order in the relation between parent-children
   - OpenGL Z might require to set 2D projection
   - cocos2d Z order works OK if all the nodes uses the same openGL Z vertex. eg: vertexZ = 0

@warning: Use it at your own risk since it might break the cocos2d parent-children z order 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章