【嘮叨】
本節要講講滾動視圖CCScrollView,相信玩過手游的同學們應該對它不會陌生吧。
例如:憤怒的小鳥的遊戲場景裡大大的地圖,手機的屏幕肯定無法完全顯示的,所以需要通過觸摸滾動才能顯示大地圖的其他區域;排行榜中上下滑動來查看其他玩家的排名;以及手機上主界面左右滑動來切換界面等等。
如下圖為屏幕滾動,切換手機的界面。
【致謝】
【Demo下載】
【3.x】
(1)去掉 「CC」
(2)滾動方向
> CCScrollViewDirection 改為強枚舉 ScrollView::Direction
(3)其他變化不大。
【CCScrollView】
滾動視圖類CCScrollView繼承於CCLayer,故它會忽略錨點的設置,其錨點始終為(0,0)。而我們知道CCLayer繼承了觸控事件CCTouch相關的函數。而CCScrollView也繼承了觸控函數,並將屏幕觸控事件的四個函數ccTouchesBegan、ccTouchesMoved、ccTouchesEnded、ccTouchesCancelled進行了重寫並實現了有關觸摸移動相關的操作(其內部的實現代碼自己看cocos2dx的源碼)。這也就是為什麼滾動視圖CCScrollView的屏幕可以進行上下左右滾動的原因了。
值得注意的是:既然CCScrollView也是一個CCLayer圖層,我們都知道觸控滾動的不是CCLayer圖層,而是添加在圖層上的那些對象。比如CCSprite精靈、以及圖層上的CCLayer等等。為了方便實現CCScrollView的滾動效果,cocos2dx引擎規定在使用CCScrollView時,需要在它的上面添加一個用於觸控滾動的容器Container,一般容器都選用CCLayer類或其擴展類(如CCLayerColor等)。而觸控事件的四個函數也是針對容器Container進行操作的。
也就是說CCScrollView實現的視圖滾動,在真正意義上說是對容器Container進行滾動。
接下來就來講講它的使用方法吧!
1、引入頭文件和命名空間
1
2
3
4
|
#include "cocos-ext.h"
using namespace cocos2d::extension;
|
2、創建方式
說明:有兩種創建方式。對於默認的創建方式create(),會自動創建CCLayer作為滾動視圖的容器,且滾動視圖的可視區域的大小默認為200*200。而第二種則是可以自定義選擇哪個CCLayer作為容器。
值得注意的是:創建滾動視圖之後,對於添加子節點操作scrollView->addChild(sp),實際上是將sp添加到容器container中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class CCScrollView : public CCLayer
static CCScrollView* create();
static CCScrollView* create(CCSize size, CCNode* container = NULL);
CCLayer* scrollLayer = CCLayer::create();
CCScrollView* scrollView = CCScrollView::create(CCSizeMake(150, 100), scrollLayer);
|
3、常用操作
設置容器、尺寸大小、容器的偏移量、允許滾動的方向、放縮、以及其他屬性的判斷。
注意:因為容器與滾動視圖的錨點均為(0,0)。所以容器的偏移量,指容器左下角坐標相對滾動視圖左下角坐標的偏移。
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
|
void setContainer(CCNode* pContainer);
CCNode* getContainer();
virtual void setContentSize( const CCSize & size);
virtual const CCSize& getContentSize() const ;
void setContentOffset(CCPoint offset, bool animated = false );
void setContentOffsetInDuration(CCPoint offset, float dt);
CCPoint getContentOffset();
void setViewSize(CCSize size);
CCSize getViewSize();
virtual void setDirection(CCScrollViewDirection eDirection);
CCScrollViewDirection getDirection();
void setZoomScale( float s);
void setZoomScale( float s, bool animated);
float getZoomScale();
void setZoomScaleInDuration( float s, float dt);
bool isDragging();
bool isTouchMoved();
void setBounceable( bool bBounceable);
bool isBounceable();
void setTouchEnabled( bool e);
|
4、事件委託代理接口類CCScrollViewDelegate
CCScrollViewDelegate類主要是用來偵聽CCScrollView的事件,並設置事件的回調響應函數。
使用方法:在創建CCScrollView類的CCLayer類中,讓CCLayer繼承CCScrollViewDelegate,並重寫如下兩個事件回調響應函數。
1
2
3
4
|
virual void scrollViewDidScroll(CCScrollView * view);
virual void scrollViewDidZoom(CCScrollView * view);
|
5、委託代理
1
2
3
4
5
6
7
8
9
10
|
void setDelegate(CCScrollViewDelegate* pDelegate);
CCScrollViewDelegate* getDelegate();
|
6、關於尺寸大小
CCScrollView的使用過程中涉及到兩個尺寸大小。
(1)滾動視圖的尺寸大小:即可視區域的大小。使用setViewSize()進行設置。
(2)容器的尺寸大小:使用setContentSize()進行設置。
例如設置滾動視圖尺寸大小為100*100,容器的尺寸大小為1000*1000。那麼每次對視圖進行滾動,都只能看到容器100*100的某部分區域。
7、關於觸摸滾動
使用setDirection()可以設置滾動的方向。主要有三個類型:
(1)橫向縱向都能滾動 kCCScrollViewDirectionBoth
(2)只能橫向滾動 kCCScrollViewDirectionHorizontal
(3)只能縱向滾動 kCCScrollViewDirectionVertical
另外setTouchEnabled()是用來設置是否開啟觸控事件的。所以若設置為false。那麼即使setDirection()了,也無法滾動視圖。
8、使用技巧
(1)創建CCScrollView,和容器CCLayer;並設置滾動視圖的容器為該容器。
(2)設置容器的尺寸大小setContentSize;滾動視圖(可視區域)的尺寸大小setViewSize。
(3)將各種精靈、菜單、按鈕等加入到容器中。
(4)設置委託代理setDelegate(this),並實現回調函數。
【代碼實戰】
這裡例舉了滾動視圖CCScrollView的三種用途。
1
2
3
4
5
|
void test1();
void test2();
void test3();
|
1、資源圖片
第一組:
第二組:
第三組:
2、引入頭文件和命名空間
1
2
3
4
|
#include "cocos-ext.h"
using namespace cocos2d::extension;
|
3、繼承CCScrollViewDelegate,重寫事件偵聽函數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class HelloWorld : public cocos2d::CCLayer, public CCScrollViewDelegate
{
public :
virtual bool init();
static cocos2d::CCScene* scene();
void menuCloseCallback(CCObject* pSender);
CREATE_FUNC(HelloWorld);
void test1();
void test2();
void test3();
int pageNumber;
CCMenuItemImage* pBack;
CCMenuItemImage* pFront;
void scrollImage(CCObject* sender);
void scrollViewDidScroll(CCScrollView* view);
void scrollViewDidZoom(CCScrollView* view);
};
|
4、委託代理回調函數
在控制台輸出LOG。
1
2
3
4
5
6
7
8
9
10
|
void HelloWorld::scrollViewDidScroll(CCScrollView* view)
{
CCLOG( "ScrollView Moved!" );
}
void HelloWorld::scrollViewDidZoom(CCScrollView* view)
{
CCLOG( "ScrollView Scaled" );
}
|
5、測試圖片滾動test1()
屏幕大小:480*320。滾動視圖大小:480*320。容器大小:960*600。
開啟彈性效果setBounceable。
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
|
void HelloWorld::test1()
{
CCSize visableSize = CCSizeMake(480, 320);
CCSize mysize = CCSizeMake(960,600);
CCLayerColor* scrollLayer = CCLayerColor::create( ccc4(255,255,255,255) );
scrollLayer->setContentSize(mysize);
CCSprite* bg = CCSprite::create( "war.png" );
bg->setPosition( ccp(960/2.0, 600/2.0) );
scrollLayer->addChild(bg);
CCScrollView* scrollView = CCScrollView::create();
this ->addChild(scrollView, 0, 1);
scrollView->setContainer(scrollLayer);
scrollView->setViewSize( visableSize );
scrollView->setBounceable( true );
scrollView->setDelegate( this );
}
|
6、測試只能縱向滾動test2()
屏幕大小:480*320。滾動視圖大小:150*100。容器大小:150*220。
將滾動視圖設置到屏幕中心位置,並設置滾動方向setDirection,只能縱向滾動。
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
|
void HelloWorld::test2()
{
CCSize visableSize = CCSizeMake(480, 320);
CCSize mysize = CCSizeMake(150,220);
CCLayerColor* scrollLayer = CCLayerColor::create( ccc4(255,255,255,255) );
scrollLayer->setContentSize(mysize);
for ( int i = 1; i <= 4; i++)
{
char file[20];
sprintf (file, "btn%d.png" , i);
CCSprite* btn = CCSprite::create(file);
btn->setPosition( ccp(mysize.width/2, 220 - 50*i) );
scrollLayer->addChild(btn);
}
CCScrollView* scrollView = CCScrollView::create(CCSizeMake(150, 100), scrollLayer);
scrollView->setPosition( visableSize/2 - ccp(150/2.0, 100/2.0) );
this ->addChild(scrollView, 0, 2);
scrollView->setDirection(kCCScrollViewDirectionVertical);
scrollView->setDelegate( this );
}
|
7、測試背包翻頁test3()
屏幕大小:480*320。滾動視圖大小:100*80。容器大小:300*80。
關閉觸控事件setTouchEnabled(false),創建兩個按鈕,實現只能通過按鈕進行左右翻頁。
翻頁原理:通過設置容器的偏移值setContentOffset。
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
|
void HelloWorld::test3()
{
CCSize visableSize = CCSizeMake(480, 320);
CCSize mysize = CCSizeMake(300,80);
CCLayerColor* scrollLayer = CCLayerColor::create( ccc4(255,255,255,255) );
scrollLayer->setContentSize(mysize);
for ( int i = 1; i <= 3; i++)
{
char file[20];
sprintf (file, "sp%d.png" , i);
CCSprite* sp = CCSprite::create(file);
sp->setPosition( ccp(100*i - 50, 40) );
scrollLayer->addChild(sp);
}
CCScrollView* scrollView = CCScrollView::create(CCSizeMake(100, 80), scrollLayer);
scrollView->setPosition( visableSize/2 - ccp(100/2.0, 0) );
this ->addChild(scrollView, 0, 3);
scrollView->setTouchEnabled( false );
scrollView->setDelegate( this );
pBack = CCMenuItemImage::create( "b1.png" , "b2.png" , "b3.png" , this , menu_selector(HelloWorld::scrollImage) );
pFront = CCMenuItemImage::create( "f1.png" , "f2.png" , "f3.png" , this , menu_selector(HelloWorld::scrollImage) );
pBack->setPosition( ccp(visableSize.width/2 - 100, 60) );
pFront->setPosition( ccp(visableSize.width/2 + 100, 60) );
CCMenu* pMenu = CCMenu::create(pBack, pFront, NULL);
pMenu->setPosition(CCPointZero);
this ->addChild(pMenu, 0, 100);
pBack->setEnabled( false );
pageNumber = 0;
}
void HelloWorld::scrollImage(CCObject* sender)
{
CCScrollView* scrollView = (CCScrollView*) this ->getChildByTag(3);
if (sender == pBack && pBack->isEnabled() )
{
pageNumber = max(0, pageNumber-1);
}
else if ( pFront->isEnabled() )
{
pageNumber = min(2, pageNumber+1);
}
scrollView->setContentOffset(ccp(-100 * pageNumber, 0), true );
pBack->setEnabled( pageNumber != 0);
pFront->setEnabled( pageNumber != 2);
}
|
8、運行結果
8.1、背景滾動、附帶彈性效果
8.2、只能縱向滾動,附帶彈性效果
8.3、背包翻頁、無法觸摸滾動、通過按鈕進行翻頁