cocos2d-x CCScrollView和CCTableView的使用

在游戏和应用中经常要实现左右滑动展示游戏帮助、以列表显示内容的UI效果,就像android中的Gallery和ListView。本文通过CCScrollView和CCTableView分别来实现这两个效果,基于cocos2d-x 2.0.4版本。
首先来简单了解一下这两个东东,CCScrollView本身是一个CCLayer,而CCTableView是CCScrollView的子类,这是引擎已经帮我们封装好了的,CCTableView可以设置成横向和纵向,用它可以实现类似于Gallery和ListView的效果。
1. 首先实现游戏帮助界面
(1) 创建头文件GalleryLayer.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef GALLERY_LAYER_H
#define GALLERY_LAYER_H
 
#include "cocos2d.h"
#include "SimpleAudioEngine.h"
#include "cocos-ext.h"
 
USING_NS_CC;
USING_NS_CC_EXT;
 
class GalleryLayer : public cocos2d::CCLayer , public CCScrollViewDelegate
{
public :
     virtual bool init(); 
 
     void menuCloseCallback(CCObject* pSender);
 
     CREATE_FUNC(GalleryLayer);
 
public :
     //scrollview滚动的时候会调用
     void scrollViewDidScroll(CCScrollView* view);
     //scrollview缩放的时候会调用
     void scrollViewDidZoom(CCScrollView* view);
 
     virtual void onEnter();
     virtual void onExit();
 
     virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
     virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
     virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
     virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
 
private :
     //根据手势滑动的距离和方向滚动图层
      void adjustScrollView( float offset);
      CCScrollView *m_pScrollView;
      CCPoint m_touchPoint;
      int m_nCurPage;
};
 
#endif

类GalleryLayer继承了CCScrollViewDelegate,实现了它的两个纯虚函数,主要是为了当scrollview滚动和缩放时回调这两函数,这样我们就可以在这两函数中做相关操作了。

(2) 看源文件GalleryLayer.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "GalleryLayer.h"
#include "ListViewLayer.h"
 
using namespace cocos2d;
using namespace cocos2d::extension;
 
bool GalleryLayer::init()
{
     bool bRet = false ;
     do
     {
        CC_BREAK_IF( !CCLayer::init() );
 
        m_nCurPage = 1;
        CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
        CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
 
        CCLayer *pLayer = CCLayer::create();
        char helpstr[30] = {0};
        for ( int i = 1; i <= 3; ++ i)
        {
            memset (helpstr, 0, sizeof (helpstr));
            sprintf (helpstr, "bg_%02d.png" ,i);
            CCSprite *pSprite = CCSprite::create(helpstr);
            pSprite->setPosition(ccp(visibleSize.width * (i-0.5f), visibleSize.height / 2));
            pLayer->addChild(pSprite);
        }
 
        m_pScrollView = CCScrollView::create(CCSizeMake(960, 640), pLayer);
        m_pScrollView->setContentOffset(CCPointZero);
        m_pScrollView->setTouchEnabled( false );
        m_pScrollView->setDelegate( this );
        m_pScrollView->setDirection(kCCScrollViewDirectionHorizontal);
        pLayer->setContentSize(CCSizeMake(960*3, 640));
 
        this ->addChild(m_pScrollView);
 
        CCSpriteFrameCache *pCache =  CCSpriteFrameCache::sharedSpriteFrameCache();
 
        pCache->addSpriteFrame(CCSpriteFrame::create( "button_normal.png" ,CCRectMake(0, 0, 64, 64)), "button_normal.png" );
        pCache->addSpriteFrame(CCSpriteFrame::create( "button_selected.png" ,CCRectMake(0, 0, 64, 64)), "button_selected.png" );
        for ( int i = 1; i <= 3; ++ i)
        {
            CCSprite *pPoint = CCSprite::createWithSpriteFrameName( "button_normal.png" );
            pPoint->setTag(i);
            pPoint->setPosition(ccp( origin.x + (visibleSize.width - 3 * pPoint->getContentSize().width)/2 + pPoint->getContentSize().width * (i-1), origin.y + 30));
            this ->addChild(pPoint);
        }
         CCSprite *pPoint = (CCSprite *) this ->getChildByTag(1);
         pPoint->setDisplayFrame(pCache->spriteFrameByName( "button_selected.png" ));
 
         bRet = true ;
     } while (0);
 
     return bRet;
 
}
 
void GalleryLayer::menuCloseCallback(CCObject* pSender)
{
 
}
 
void GalleryLayer::scrollViewDidScroll(cocos2d::extension::CCScrollView *view)
{
     CCLOG( "scroll" );
}
 
void GalleryLayer::scrollViewDidZoom(cocos2d::extension::CCScrollView *view)
{
     CCLOG( "zoom" );
}
 
void GalleryLayer::onEnter()
{
     CCLayer::onEnter();
     CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate( this , 1, false );
}
 
void GalleryLayer::onExit()
{
     CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate( this );
     CCLayer::onExit();
     CCSpriteFrameCache::sharedSpriteFrameCache()->removeUnusedSpriteFrames();
}
 
bool GalleryLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
     m_touchPoint = CCDirector::sharedDirector()->convertToGL(pTouch->getLocationInView());
     return true ;
}
 
void GalleryLayer::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
 
}
 
void GalleryLayer::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
     CCPoint endPoint = CCDirector::sharedDirector()->convertToGL(pTouch->getLocationInView());
     float distance = endPoint.x - m_touchPoint.x;
     if ( fabs (distance) > 50)
     {
         adjustScrollView(distance);
     }
}
 
void GalleryLayer::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
     CCPoint endPoint = CCDirector::sharedDirector()->convertToGL(pTouch->getLocationInView());
     float distance = endPoint.x - m_touchPoint.x;
     if ( fabs (distance) > 50)
     {
         adjustScrollView(distance);
     }
}
 
void GalleryLayer::adjustScrollView( float offset)
{
     CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
     CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
     CCSpriteFrameCache *pCache =  CCSpriteFrameCache::sharedSpriteFrameCache();
     CCSprite *pPoint = (CCSprite *) this ->getChildByTag(m_nCurPage);
     pPoint->setDisplayFrame(pCache->spriteFrameByName( "button_normal.png" ));
     if (offset<0)
     {
         m_nCurPage ++;
     } else
     {
         m_nCurPage --;
     }
 
     if (m_nCurPage <1)
     {
         m_nCurPage = 1;
     }
 
     if (m_nCurPage > 3)
     {
         CCLayer *pLayer = ListViewLayer::create();
         CCScene *pScene = CCScene::create();
         pScene->addChild(pLayer);
         CCDirector::sharedDirector()->replaceScene(pScene);
     }
     else
     {
         pPoint = (CCSprite *) this ->getChildByTag(m_nCurPage);
         pPoint->setDisplayFrame(pCache->spriteFrameByName( "button_selected.png" ));
         CCPoint  adjustPos = ccp(origin.x - visibleSize.width * (m_nCurPage-1), 0);
         m_pScrollView->setContentOffset(adjustPos, true );
     }
}

这里一共有三张图,是从捕鱼达人中拿出来的背景图,当滚完三张图时就跳转到ListViewLayer场景去,上面的代码比较容易懂。
首先创建一个CCLayer,包含三张背景图,设置CCLayer的ContentSize,并设置三张图片的位置
然后设置CCLayer为CCScrollview的内容,并设置CCScrollView的显示区域。
最后根据用户滑动的方向和距离,通过设置scrollview的setContentOffset,滚动视图。
CCScrollview.h文件中封装了一个枚举类型,一共有四个方向,常用横向和纵向,这里使用了横向。

1
2
3
4
5
6
typedef enum {
     kCCScrollViewDirectionNone = -1,
     kCCScrollViewDirectionHorizontal = 0,
     kCCScrollViewDirectionVertical,
     kCCScrollViewDirectionBoth
} CCScrollViewDirection;

下面来看看这部分的效果:

2. 现在来实现列表展示(ListView)的效果
(1)创建ListViewLayer.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef LISTVIEW_LAYER_H
#define LISTVIEW_LAYER_H
 
#include "cocos2d.h"
#include "cocos-ext.h"
 
class ListViewLayer : public cocos2d::CCLayer, public cocos2d::extension::CCTableViewDataSource, public cocos2d::extension::CCTableViewDelegate
{
public :
     virtual bool init(); 
 
     virtual void scrollViewDidScroll(cocos2d::extension::CCScrollView* view);
 
     virtual void scrollViewDidZoom(cocos2d::extension::CCScrollView* view);
 
     //处理触摸事件,可以计算点击的是哪一个子项
     virtual void tableCellTouched(cocos2d::extension::CCTableView* table, cocos2d::extension::CCTableViewCell* cell);
     //每一项的宽度和高度
     virtual cocos2d::CCSize cellSizeForTable(cocos2d::extension::CCTableView *table);
     //生成列表每一项的内容
     virtual cocos2d::extension::CCTableViewCell* tableCellAtIndex(cocos2d::extension::CCTableView *table, unsigned int idx);
     //一共多少项
     virtual unsigned int numberOfCellsInTableView(cocos2d::extension::CCTableView *table);
 
     CREATE_FUNC(ListViewLayer);
};
 
#endif

ListViewLayer继承了CCTableViewDataSource和CCTableViewDelegate。这两个抽象类封装了几个有用的函数,我们在下面的源码中将实现它们。
(2)源文件 ListViewLayer.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "ListViewLayer.h"
 
USING_NS_CC;
USING_NS_CC_EXT;
 
bool ListViewLayer::init()
{
     bool bRet = false ;
     do
     {
         CC_BREAK_IF( !CCLayer::init() );
 
         CCTableView* pTableView = CCTableView::create( this , CCSizeMake(960, 640));
         pTableView->setDirection(kCCScrollViewDirectionVertical);
         pTableView->setPosition(CCPointZero);
         pTableView->setDelegate( this );
         pTableView->setVerticalFillOrder(kCCTableViewFillTopDown);
         this ->addChild(pTableView);
         pTableView->reloadData();
 
         bRet = true ;
     } while (0);
 
     return bRet;
}
 
void ListViewLayer::tableCellTouched(CCTableView* table, CCTableViewCell* cell)
{
     CCLog( "cell touched at index: %i" , cell->getIdx());
}
 
CCSize ListViewLayer::cellSizeForTable(CCTableView *table)
{
     return CCSizeMake(960, 120);
}
 
CCTableViewCell* ListViewLayer::tableCellAtIndex(CCTableView *table, unsigned int idx)
{
     CCString *pString = CCString::createWithFormat( "%d" , idx);
     CCTableViewCell *pCell = table->dequeueCell();
     if (!pCell) {
         pCell = new CCTableViewCell();
         pCell->autorelease();
         CCSprite *pSprite = CCSprite::create( "listitem.png" );
         pSprite->setAnchorPoint(CCPointZero);
         pSprite->setPosition(CCPointZero);
         pCell->addChild(pSprite);
 
         CCLabelTTF *pLabel = CCLabelTTF::create(pString->getCString(), "Arial" , 20.0);
         pLabel->setPosition(CCPointZero);
         pLabel->setAnchorPoint(CCPointZero);
         pLabel->setTag(123);
         pCell->addChild(pLabel);
     }
     else
     {
         CCLabelTTF *pLabel = (CCLabelTTF*)pCell->getChildByTag(123);
         pLabel->setString(pString->getCString());
     }
 
     return pCell;
}
 
unsigned int ListViewLayer::numberOfCellsInTableView(CCTableView *table)
{
     return 20;
}
 
void ListViewLayer::scrollViewDidScroll(CCScrollView *view)
{
}
 
void ListViewLayer::scrollViewDidZoom(CCScrollView *view)
{
}

首先需要创建CCTableView,设置它的显示区域和显示方向,这里使用了纵向。设置每个子项的宽度和高度,子项的数量以及每个子项对应的内容。每个子项是一个CCTableViewCell,这里进行了优化,复用了子项对象。
下面是效果图:

源码下载地址:http://download.csdn.net/detail/zhoujianghai/4975604

转载请注明来自:Alex Zhou的程序世界,本文链接:http://codingnow.cn/cocos2d-x/1024.html

你可能感兴趣的:(Cocos2d-x)