直接上代码:
HelloWorldScene.cpp
#include "HelloWorldScene.h"
USING_NS_CC;
#define COIN_WIDTH 212 //coin 图片宽度
#define COIN_GAP 100 //间隔
#define COIN_COUNT 11 //个数
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//
// 1. super init first
if ( !Layer::init() )
{
return false;
}
Size visibleSize = Director::getInstance() -> getVisibleSize();
//XKPageView::create(Size size,XKPageViewDelegate *delegate)
pageView = XKPageView::create(Size(visibleSize.width, COIN_WIDTH), this);
pageView -> setDirection(ScrollView::Direction::HORIZONTAL);
//container 定位在屏幕中间
pageView -> setPosition(Point((visibleSize.width - COIN_WIDTH) * 0.5, (visibleSize.height - COIN_WIDTH) * 0.5));
addPages();
//设置裁切为false, 这样layer 溢出pageView的Size还能显示
pageView -> setClippingToBounds(false);
this -> addChild(pageView);
//设置pageView 自动调整时的callback,可以在这里写你要的功能
pageView -> adjustCallback = [](XKPageView *pageView){
FiniteTimeAction *fadeIn = FadeTo::create(0.15, 255);
FiniteTimeAction *fadeOut = FadeTo::create(0.15, 255 * 0.3);
FiniteTimeAction *scaleToBig = ScaleTo::create(0.15, 1.5f);
FiniteTimeAction *scaleToSmall = ScaleTo::create(0.15, 1.0f);
Spawn *spawnIn = Spawn::createWithTwoActions(fadeIn, scaleToBig);
Spawn *spawnOut = Spawn::createWithTwoActions(fadeOut, scaleToSmall);
int current = pageView -> getCurrentIndex();
auto sprite = (Sprite*) pageView -> getPageAtIndex(current);
sprite -> runAction(spawnIn);
sprite = (Sprite *)pageView -> getPageAtIndex(current - 1);
if (sprite !=NULL){
sprite -> runAction(spawnOut);
}
sprite = (Sprite *)pageView -> getPageAtIndex(current + 1);
if (sprite !=NULL){
sprite -> runAction(spawnOut -> clone());
}
};
return true;
}
void HelloWorld::addPages()
{
Size coinSize = Sprite::create("coin.png") -> getContentSize();
//11个layer 加到layer 上
for (int i = 0; i < COIN_COUNT; i++) {
auto sprite = Sprite::create("coin.png");
sprite -> setPosition(coinSize.width * 0.5, coinSize.height * 0.5);
std::string str = StringUtils::format("%d", i);
Label *label = Label::createWithSystemFont(str, "Arial", 60);
label -> setTextColor(Color4B(0,0,0,255));
Size size = sprite -> getContentSize();
label -> setPosition(size.width * 0.5, size.height * 0.5);
sprite -> addChild(label);
//注意这里使用的时XKPageView 的addPage, 不是addChild
pageView -> addPage(sprite);
}
}
Size HelloWorld::sizeForPerPage()
{
//Delegate 的东西,返回每个Page 的Size
return Size(COIN_WIDTH + COIN_GAP, COIN_WIDTH);
}
void HelloWorld::pageViewDidScroll(XKPageView *pageView)
{
//监听滚动时间,可以再这里写滚动时候要添加的代码,比如缩放~
Size visibleSize = Director::getInstance() -> getVisibleSize();
float midX = visibleSize.width / 2;
float offsetX = pageView -> getContentOffset().x;
float tmp = COIN_WIDTH / 2.0f;
float scale = 1.5;
scale = scale - 1;
for (int i = 0; i < COIN_COUNT; i++) {
auto sprite = (Sprite *) pageView -> getPageAtIndex(i);
float positionX = sprite -> getPositionX();
//转换成相对屏幕坐标
float endX = positionX + offsetX + midX - tmp;
if (0 < endX && endX <= midX) {
float x = endX / midX * scale + 1;
sprite -> setScale(x);
x = (endX / midX * 0.7 + 0.3) * 255;
sprite -> setOpacity(x);
}else if(endX > midX && endX < visibleSize.width){
float tmp2 = endX - midX;
tmp2 = midX - tmp2;
float x = tmp2 / midX * scale + 1;
sprite -> setScale(x);
x = (tmp2 / midX * 0.7 + 0.3) * 255;
sprite -> setOpacity(x);
}else {
sprite -> setScale(1.0f);
sprite -> setOpacity(255 * 0.3);
}
}
}
void HelloWorld::onEnter()
{
Layer::onEnter();
pageView -> adjustCallback(pageView);
}
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "extensions/cocos-ext.h"
#include "XKPageView.h"
USING_NS_CC_EXT;
class HelloWorld : public cocos2d::Layer, public XKPageViewDelegate
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
// PageViewDelegate
virtual Size sizeForPerPage();
virtual void pageViewDidScroll(XKPageView *pageView);
private:
XKPageView *pageView;
void addPages();
public:
virtual void onEnter();
};
#endif // __HELLOWORLD_SCENE_H__
XKPageView.h
//
// XKPageView.h
// XKPageView
//
// Created by Joueu on 14-11-26.
//
//
#ifndef __XKPageView__XKPageView__
#define __XKPageView__XKPageView__
#include "cocos2d.h"
#include "extensions/cocos-ext.h"
USING_NS_CC;
USING_NS_CC_EXT;
class XKPageView;
class XKPageViewDelegate
{
public:
virtual ~XKPageViewDelegate(){};
XKPageViewDelegate(){};
//获取Page大小
virtual Size sizeForPerPage() = 0;
//滚动回调
virtual void pageViewDidScroll(XKPageView *pageView){};
};
class XKPageView:public ScrollView
{
public:
static XKPageView *create(Size size,XKPageViewDelegate *delegate);
virtual bool init(Size size,XKPageViewDelegate *delegate);
public:
void setPageSize(Size size);
virtual void setContentOffsetInDuration(Vec2 offset, float dt);
virtual void setContentOffset(Vec2 offset);
private:
void performedAnimatedScroll(float dt);
int current_index;
float current_offset;
//调整offset 的函数
void adjust(float offset);
Size pageSize;
CC_SYNTHESIZE(XKPageViewDelegate *, _delegate, Delegate);
public:
int pageCount;
void addPage(Node *node);
Node *getPageAtIndex(int index);
int getCurrentIndex();
//滚动后调整回调
std::function<void(XKPageView *)> adjustCallback;
};
#endif /* defined(__XKPageView__XKPageView__) */
//
// XKPageView.cpp
// XKPageView
//
// Created by Joueu on 14-11-26.
//
//
#include "XKPageView.h"
#define XKPAGEVIEW_TAG 10086
XKPageView *XKPageView::create(Size size,XKPageViewDelegate *delegate)
{
XKPageView *page = new XKPageView();
if (page && page -> init(size,delegate)) {
page -> autorelease();
}else {
CC_SAFE_RELEASE(page);
}
return page;
}
bool XKPageView::init(Size size,XKPageViewDelegate *delegate)
{
if (!ScrollView::initWithViewSize(size)) {
return false;
}
//必须有delegate,否则断掉
CCASSERT(delegate, "delegate should not be NULL!");
setDelegate(delegate);
if (_delegate) {
//获取page的大小
pageSize = _delegate -> sizeForPerPage();
}
//init Data
pageCount = 0;
current_index = 0;
this -> setTouchEnabled(false);
auto listener = EventListenerTouchOneByOne::create();
listener -> onTouchBegan = [&](Touch *touch, Event *event){
_dragging = false;
this -> scheduleUpdate();
if (_direction == ScrollView::Direction::HORIZONTAL) {
current_offset = this -> getContentOffset().x;
}else {
current_offset = this -> getContentOffset().y;
}
return true;
};
listener -> onTouchMoved = [&](Touch *touch, Event *event){
float start, end;
if (_direction == ScrollView::Direction::HORIZONTAL) {
start = touch -> getStartLocation().x;
end = touch -> getLocation().x;
}else {
start = touch -> getStartLocation().y;
end = touch -> getLocation().y;
}
float offset = end - start;
// * 2的作用是调节滚动速度,需要调滑动速度的 可以改这个值
if (_direction == ScrollView::Direction::HORIZONTAL)
this -> setContentOffset(Vec2(current_offset + offset * 2, 0));
else
this -> setContentOffset(Vec2(0, current_offset + offset * 2));
};
listener -> onTouchEnded = [&](Touch *touch, Event *event){
float start = current_offset, end;
if (_direction == ScrollView::Direction::HORIZONTAL) {
end = this -> getContentOffset().x;
}else {
end = this -> getContentOffset().y;
}
float offset = end - start;
this -> adjust(offset);
_dragging = true;
};
Director::getInstance() -> getEventDispatcher() -> addEventListenerWithSceneGraphPriority(listener, this);
return true;
}
void XKPageView::adjust(float offset)
{
Vec2 vec;
float xOrY;
if (_direction == ScrollView::Direction::HORIZONTAL) {
vec = Vec2(-( current_index * (pageSize.width)),0);
xOrY = pageSize.width;
}else {
vec = Vec2(0, -( current_index * (pageSize.height)));
xOrY = pageSize.height;
}
//小于50回到原来位置
if (abs(offset) < 50){
this -> setContentOffsetInDuration(vec,0.15f);
return;
}
int i = abs(offset / (xOrY)) + 1;
if (offset < 0) {
current_index += i;
}else {
current_index -= i;
}
if (current_index < 0) {
current_index = 0;
}else if(current_index > 10){
current_index = 10;
}
if (_direction == ScrollView::Direction::HORIZONTAL) {
vec = Vec2(-( current_index * (pageSize.width)),0);
}else {
vec = Vec2(0, -( current_index * (pageSize.height)));
}
this -> adjustCallback(this);
this -> setContentOffsetInDuration(vec, 0.15f);
}
void XKPageView::setContentOffset(Vec2 offset)
{
ScrollView::setContentOffset(offset);
if (_delegate != nullptr)
{
_delegate -> pageViewDidScroll(this);
}
}
void XKPageView::setContentOffsetInDuration(Vec2 offset, float dt)
{
ScrollView::setContentOffsetInDuration(offset, dt);
this->schedule(schedule_selector(XKPageView::performedAnimatedScroll));
}
void XKPageView::performedAnimatedScroll(float dt)
{
if (_dragging)
{
this->unschedule(schedule_selector(XKPageView::performedAnimatedScroll));
this -> unscheduleUpdate();
return;
}
if (_delegate != nullptr)
{
_delegate -> pageViewDidScroll(this);
}
}
void XKPageView::addPage(Node *node)
{
if (_direction == ScrollView::Direction::HORIZONTAL) {
node -> setPosition(Point(pageCount * pageSize.width + node -> getPositionX(),node -> getPositionY()));
this -> setContentSize(Size((pageCount + 1) * pageSize.width,pageSize.height));
}else {
node -> setPosition(Point(node -> getPositionX(),pageCount * pageSize.height + node -> getPositionY()));
this -> setContentSize(Size(pageSize.width,(pageCount + 1) *pageSize.height));
}
node -> setTag(pageCount + XKPAGEVIEW_TAG);
_container -> addChild(node);
pageCount ++;
}
Node *XKPageView::getPageAtIndex(int index)
{
if (index < pageCount && index >= 0) {
return _container -> getChildByTag(index + XKPAGEVIEW_TAG);
}
return NULL;
}
int XKPageView::getCurrentIndex()
{
return current_index;
}
文章转自: http://helkyle.tk/cocos-2dx-3xPageView/