1、概述
2、四種點擊
1、函數回調
- // a selector callback
- void menuCloseCallback(Object* pSender);
- auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",
- CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
- void HelloWorld::menuCloseCallback(Object* pSender)
- {
- Director::getInstance()->end();
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
- exit(0);
- #endif
- }
其中CC_CALLBACK_1宏是將函數與對象綁定在一起,1表示這個函數有一個參數。當點擊這個按鈕時,會調用這個回調函數。
除了基於c++11的這個形式的改變,使用方法與先前相同。
此種方式已經被捨棄,可以使用第四種方法做替代。
2、Layer的touch消息響應
雖然重寫了底層的dispatch,但對這層的使用影響並不大。我們同樣需要重寫:
- //單點響應
- virtual bool onTouchBegan(Touch* touch, Event *event) override;
- virtual void onTouchMoved(Touch* touch, Event *event) override;
- virtual void onTouchEnded(Touch* touch, Event *event) override;
- virtual void onTouchCancelled(Touch *touch, Event *event) override;
- //多點響應
- virtual bool onTouchesBegan(Touch* touch, Event *event) override;
- virtual void onTouchesMoved(Touch* touch, Event *event) override;
- virtual void onTouchesEnded(Touch* touch, Event *event) override;
- virtual void onTouchesCancelled(Touch *touch, Event *event) override;
重寫這些函數來對layer的點擊做處理。當然,我們需要:
- setTouchEnabled(true)。
此外有個小改動。對於單點觸控響應,可以調用:
- //設置爲單點響應
- setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
- //設置爲多點響應(默認)
- setTouchMode(Touch::DispatchMode::ALL_AT_ONCE);
進行設置,而不需要再用設置Delegate的方式來做了。
3、TouchEvent響應
- //聲明
- void touchButton(Object* object,TouchEventType type);
- //掛接到控件上
- uiButton->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton));
- //實現
- void HelloWorld::touchButton(Object* object,TouchEventType type)
- {
- LabelTTF* label;
- switch (type)
- {
- case TouchEventType::TOUCH_EVENT_BEGAN:
- label = static_cast<LabelTTF*>(getChildByTag(11));
- label->setString("按下按鈕");
- break;
- case TouchEventType::TOUCH_EVENT_MOVED:
- label = static_cast<LabelTTF*>(getChildByTag(11));
- label->setString("按下按鈕移動");
- break;
- case TouchEventType::TOUCH_EVENT_ENDED:
- label = static_cast<LabelTTF*>(getChildByTag(11));
- label->setString("放開按鈕");
- break;
- case TouchEventType::TOUCH_EVENT_CANCELED:
- label = static_cast<LabelTTF*>(getChildByTag(11));
- label->setString("取消點擊");
- break;
- default:
- break;
- }
- }
因爲所有的UIWidget都要添加到UILayer上,而UILayer通常作爲UI的Widget都會在最上層,所以可以“基本上”認爲這種使用方式會優先於其他方式處理點擊消息。因爲UILayer也會有層級的改變,比如它和MenuItem之間的關係。所以說“基本上”。
4、Listener消息響應方式
這種實現也是新加入的。它更像是點擊的一個層次過濾器。點擊時,在listener隊裏中進行過濾。每一個listener檢查自己保存的touch消息響應是否會被觸發。一層一層過濾,最後在到Layer的touch消息響應。
我覺得它的設計的初衷是爲任意sprite提供一套自己制定的點擊響應。但這樣的實現仍然要寫很多條件判斷,沒有能夠控件化。可能我的理解有些偏差,歡迎討論。
它被設計成一個全局點擊響應控制。具體的用法大致是這樣:
- //auto dispatcher = EventDispatcher::getInstance();
- // auto myListener = EventListenerTouch::create(Touch::DispatchMode::ONE_BY_ONE);
- auto dispatcher = Director::getInstance()->getEventDispatcher();
- auto myListener = EventListenerTouchOneByOne::create();
- //如果不加入此句消息依舊會向下傳遞
- myListener->setSwallowTouches(true);
- myListener->onTouchBegan = [=](Touch* touch,Event* event)
- {
- //some check
- if (pass)
- {
- return true;
- }
- return false;
- };
- myListener->onTouchMoved = [=](Touch* touch,Event* event)
- {
- //do something
- };
- myListener->onTouchEnded = [=](Touch* touch,Event* event)
- {
- //do something
- };
- dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite1);
- dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite2);
其原理是在dispatcher中檢查listener列表,例如myListener或加進來的其他listener。然後每個listener檢查自己中的Item看能否達到檢查條件,例如:mySprite1,mySprite2。然後執行相應的操作。但這樣的話,當控件很多的時候,每一次事件都進行這種雙鏈表的檢查操作不知會不會影響些性能?
3、實例
光說不練假把式,於是就動手寫了一個上面的Demo:
點擊背景區域可以移動整個場景,點擊藍色小方塊可以半透明移動它,點擊藍色按鈕可以更改文字,顯示狀態。點擊右下角按鈕退出程序。
項目配置可參照:
Cocos2d-x 3.0 開發(十六)cocos2dx-3.0beta版建立新項目並加載CocoStudio導出文件
4、總結
根據不同的交互需要,選擇不同的實現方式,會更有利於我們的維護和擴展,相應例子可以在下面下載。
Demo下載:http://download.csdn.net/detail/fansongy/6399291 不要資源分,覺得好勞煩點下 “頂” ~
Demo For Beta2 下載:http://download.csdn.net/detail/fansongy/6892047
本篇博客出自阿修羅道,轉載請註明出處,禁止用於商業用途:http://blog.csdn.net/fansongy/article/details/12716671