#ifndef __ScrollView_H__
#define __ScrollView_H__
#include "cocos2d.h"
#include "cocos-ext.h"
USING_NS_CC;
USING_NS_CC_EXT;
class ScrollView : public Layer
{
public:
ScrollView();
~ScrollView();
CREATE_FUNC(ScrollView);
bool init();
bool TouchBegan(Touch*, Event*);
void TouchEnded(Touch*, Event*);
void TouchMoved(Touch*, Event*);
float _lastContainerPos;
void detectContainerMoving(float);
void adjustScrollView();
ScrollView* _view;
};
#endif
<pre name="code" class="html">#include "ScrollView.h"
ScrollView::ScrollView()
{
}
ScrollView::~ScrollView()
{
}
bool ScrollView::init()
{
Layer::init();
auto winSize = Director::getInstance()->getWinSize();
// create时候的参数size,指所见的尺寸,不是内容的尺寸
ScrollView* view = ScrollView::create(winSize);
_view = view;
addChild(view);
// 设置内容
Node* node = view->getContainer();
for (int i = 0; i < 3; ++i)
{
char buf[1024];
sprintf(buf, "Images/background%d.png", i + 1);
Sprite* sprite = Sprite::create(buf);
node->addChild(sprite);
sprite->setPosition(winSize.width / 2 + i*winSize.width, winSize.height/2);
sprite->setTag(i);
}
//node->setContentSize(Size(winSize.width * 3, winSize.height));
view->setContentSize(Size(winSize.width * 3, winSize.height));
// 额外设置
view->setDirection(ScrollView::Direction::HORIZONTAL);
// view->setBounceable(false);
/*
调整Scroll
1. 增加触摸处理
*/
auto ev = EventListenerTouchOneByOne::create();
ev->onTouchBegan = CC_CALLBACK_2(ScrollView::TouchBegan, this);
ev->onTouchMoved = CC_CALLBACK_2(ScrollView::TouchMoved, this);
ev->onTouchEnded = CC_CALLBACK_2(ScrollView::TouchEnded, this);
this->_eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);
return true;
}
bool ScrollView::TouchBegan(Touch*, Event*)
{
return true;
}
void ScrollView::TouchEnded(Touch* touch, Event*)
{
Vec2 delta = touch->getLocation() - touch->getStartLocation();
if (delta.getLengthSq()<25)
{
// 点击
Node* node = _view->getContainer();
Vec2 posInNode = node->convertTouchToNodeSpace(touch);
for (int i = 0; i < 3; ++i)
{
Node* sprite = node->getChildByTag(i);
if (sprite->getBoundingBox().containsPoint(posInNode))
{
CCLOG("click i=%d", i);
break;
}
}
}
else
{
// 当手指离开屏幕后,启用定时器来检测container是否停止运动
_lastContainerPos = 10000000;
schedule(schedule_selector(ScrollView::detectContainerMoving), 0.05f);
}
}
void ScrollView::detectContainerMoving(float)
{
#if 0
static int i = 0;
i++;
if (i % 2 == 0)
return;
#endif
// 获取当前Container的位置,判断位置和_lastContainerPos是否相等
Node* node = _view->getContainer();
float cur = node->getPositionX();
if (cur == _lastContainerPos)
{
// 开始调整
unschedule(schedule_selector(ScrollView::detectContainerMoving));
adjustScrollView();
}
else
{
_lastContainerPos = cur;
}
}
void ScrollView::adjustScrollView()
{
auto winSize = Director::getInstance()->getWinSize();
//获取所有的Container中的精灵,判断精灵位置到窗口中心的距离,找到最近的距离
float distNearest = 1000000;
int idxNearest = 0;
float moveDist;
Node* node = _view->getContainer();
for (int i = 0; i < 3; ++i)
{
Node* sprite = node->getChildByTag(i);
Vec2 pos = sprite->getPosition();
Vec2 posInWorld = node->convertToWorldSpace(pos);
float dist = abs(posInWorld.x - winSize.width / 2);
if (dist < distNearest)
{
moveDist = posInWorld.x - winSize.width / 2;
idxNearest = i;
distNearest = dist;
}
else
{
break;
}
}
// 移动Container
MoveBy* move = MoveBy::create(distNearest/200, Vec2(-moveDist, 0));
node->runAction(move);
}
void ScrollView::TouchMoved(Touch*, Event*)
{}