模拟iOS原生手势,简单实现点击(双击)、长按、滑动、拖动等功能。
代码如下:
- //
- // CGesture.h
- // ActionLabel
- //
- // Created by xujw on 16/3/15.
-
- /* 手势识别 仿iphone 简单长按 点击(双击等) 滑动 拖动等。 * 使用方法: * auto gesture = CGesture::createTapGesture(target,callback,taps); * this->addChild(gestrue) */
-
- #ifndef CGesture_h
- #define CGesture_h
-
- #include <stdio.h>
- #include "cocos2d.h"
- USING_NS_CC;
-
- typedef enum gestureDirection
- {
- kDirectUp = @H_404_30@0,kDirectDown = @H_404_30@1,kDirectLeft = @H_404_30@2,kDirectRight = @H_404_30@3
- }GestureDirection;
-
- typedef std::function<void(Touch*)> GestureCallback;
- typedef std::function<void(Touch*,GestureDirection)> SwipeGestureCallback;
-
- #define SHAKE_LENGTH 100
-
- class CGesture:public Layer
- {
- private:
- bool _isCanTouch;
- int _tapNum;
- public:
- CGesture();
- ~CGesture();
- bool init();
- CREATE_FUNC(CGesture);
- public:
- //点击
- static CGesture* createTapGesture(Node*target,GestureCallback callback,int tapsrequired=@H_404_30@1);
- //长按
- static CGesture* createLongPressGesture(Node*target,float delay = @H_404_30@1.0f);
- //滑动
- static CGesture* createSwipeGesture(Node*target,SwipeGestureCallback callback);
- //拖动
- static CGesture* createPanGestrue(Node*target,GestureCallback callback);
- };
- #endif /* CGesture_h */
-
- //
- // CGesture.cpp
- // ActionLabel
- //
- // Created by xujw on 16/3/15.
- //
- //
-
- #include "CGesture.h"
- #include <time.h>
-
- CGesture::CGesture()
- :_isCanTouch(false),_tapNum(@H_404_30@0)
- {}
- CGesture::~CGesture()
- {}
-
- bool CGesture::init()
- {
- if (!Layer::init())
- {
- return false;
- }
-
- return true;
- }
-
- CGesture* CGesture::createTapGesture(Node*target,int tapsrequired)
- {
- CCASSERT(callback && target,"callback or target is null");
-
- auto parent = target->getParent();
-
- auto gesture = CGesture::create();
-
- auto lis = EventListenerTouchOneByOne::create();
- lis->onTouchBegan = [=](Touch *touch,Event *event)
- {
- auto Box = target->getBoundingBox();
- auto pos = touch->getLocation();
- if (parent) {
- pos = parent->convertToNodeSpace(pos);
- }
- if (Box.containsPoint(pos))
- {
- gesture->_tapNum ++;
- }
-
- return true;
- };
- lis->onTouchMoved = [=](Touch *touch,Event *event)
- {
- auto startPos = touch->getStartLocation();
- auto curPos = touch->getLocation();
- auto subPos = curPos - startPos;
- if (fabs(subPos.x)>=@H_404_30@10 || fabs(subPos.y)>=@H_404_30@10)
- {
- gesture->_tapNum = @H_404_30@0;
- gesture->unschedule("GestureTapNumReset");
- }
- };
- lis->onTouchEnded = [=](Touch *touch,Event *event)
- {
- if (gesture->_tapNum >= tapsrequired)
- {
- auto Box = target->getBoundingBox();
- auto pos = touch->getLocation();
- auto parent = target->getParent();
- if (parent) {
- pos = parent->convertToNodeSpace(pos);
- }
- if (Box.containsPoint(pos))
- {
- gesture->_tapNum = @H_404_30@0;
- gesture->unschedule("GestureTapNumReset");
- callback(touch);
- }
- }
- gesture->scheduleOnce([=](float dt)
- {
- gesture->_tapNum = @H_404_30@0;
- },@H_404_30@0.5,"GestureTapNumReset");
- };
-
- gesture->getEventDispatcher()->addEventListenerWithSceneGraPHPriority(lis,target);
-
- return gesture;
- }
-
- CGesture* CGesture::createLongPressGesture(Node*target,float delay)
- {
- CCASSERT(callback && target,Event *event)
- {
- auto Box = target->getBoundingBox();
- auto pos = touch->getLocation();
- if (parent) {
- pos = parent->convertToNodeSpace(pos);
- }
- if (Box.containsPoint(pos))
- {
- gesture->scheduleOnce([=](float){
- gesture->_isCanTouch = true;
- },delay,"GestureChangeTouchState");
- return true;
- }
- else
- {
- return false;
- }
- };
- lis->onTouchMoved = [=](Touch *touch,Event *event)
- {
- //长按时滑动算取消
- auto startPos = touch->getStartLocation();
- auto curPos = touch->getLocation();
- auto subPos = curPos - startPos;
- if (fabs(subPos.x)>=@H_404_30@10 || fabs(subPos.y)>=@H_404_30@10)
- {
- gesture->unschedule("GestureChangeTouchState");
- gesture->_isCanTouch = false;
- }
- };
- lis->onTouchEnded = [=](Touch *touch,Event *event)
- {
- auto Box = target->getBoundingBox();
- auto pos = touch->getLocation();
- if (parent) {
- pos = parent->convertToNodeSpace(pos);
- }
-
- if (gesture->_isCanTouch)
- {
- if (Box.containsPoint(pos))
- {
- callback(touch);
- }
- }
- else
- {
- gesture->unschedule("GestureChangeTouchState");
- }
- gesture->_isCanTouch = false;
- };
-
- gesture->getEventDispatcher()->addEventListenerWithSceneGraPHPriority(lis,target);
-
- return gesture;
- }
-
- CGesture* CGesture::createSwipeGesture(Node*target,SwipeGestureCallback callback)
- {
- CCASSERT(callback && target,"callback or target is null");
-
- auto parent = target->getParent();
- auto gesture = CGesture::create();
-
- auto lis = EventListenerTouchOneByOne::create();
- lis->onTouchBegan = [=](Touch *touch,Event *event)
- {
- auto pos = touch->getLocation();
- auto Box = target->getBoundingBox();
- if (parent) {
- pos = parent->convertToNodeSpace(pos);
- }
- if (Box.containsPoint(pos))
- {
- gesture->_isCanTouch = true;
- }
- else{
- gesture->_isCanTouch = false;
- }
- return gesture->_isCanTouch;
- };
- lis->onTouchMoved = [=](Touch *touch,Event *event){};
- lis->onTouchEnded = [=](Touch *touch,Event *event)
- {
- auto pos = touch->getLocation();
- auto Box = target->getBoundingBox();
- if (parent) {
- pos = parent->convertToNodeSpace(pos);
- }
- //起始点都在target范围内才响应
- if (!gesture->_isCanTouch || !Box.containsPoint(pos))
- {
- gesture->_isCanTouch = false;
- return ;
- }
-
- auto startPos = touch->getStartLocation();
- auto curPos = touch->getLocation();
- auto subPos = curPos - startPos;
-
- if (fabs(subPos.x) > fabs(subPos.y))
- {
- //左右移动
- if (subPos.x > SHAKE_LENGTH)
- {
- //向右移动
- callback(touch,kDirectRight);
- }
- else if (subPos.x < -SHAKE_LENGTH)
- {
- //向左移动
- callback(touch,kDirectLeft);
- }
- }
- else
- {
- if (subPos.y > SHAKE_LENGTH)
- {
- //向上移动
- callback(touch,kDirectUp);
- }
- else if (subPos.y < -SHAKE_LENGTH)
- {
- //向下移动
- callback(touch,kDirectDown);
- }
- }
- };
- gesture->getEventDispatcher()->addEventListenerWithSceneGraPHPriority(lis,gesture);
- return gesture;
- }
-
- CGesture* CGesture::createPanGestrue(Node*target,GestureCallback callback)
- {
- CCASSERT(callback && target,Event *event)
- {
- auto Box = target->getBoundingBox();
- auto pos = touch->getLocation();
- if (parent) {
- pos = parent->convertToNodeSpace(pos);
- }
- if (Box.containsPoint(pos))
- {
- gesture->_isCanTouch = true;
- }
- return true;
- };
- lis->onTouchMoved = [=](Touch *touch,Event *event)
- {
- if (gesture->_isCanTouch)
- {
- callback(touch);
- }
- };
- lis->onTouchEnded = [=](Touch *touch,Event *event)
- {
- gesture->_isCanTouch = false;
- };
- gesture->getEventDispatcher()->addEventListenerWithSceneGraPHPriority(lis,target);
- return gesture;
- }