国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

[cocos2dx]讓CCScrollView支持分頁

2019-11-14 20:34:55
字體:
供稿:網(wǎng)友

[cocos2dx]讓CCScrollView支持分頁

做過IOS開發(fā)的朋友, 肯定知道UIScrollView有一個isPaged屬性. 當設置其為true的時候, 滑動會自動分頁. 即, 每次滑動之后, 會停止在整頁的位置. 當開始介入cocos2dx開發(fā)的時候, 卻發(fā)現(xiàn)跟UIScrollView接口十分相似的CCScrollView卻沒有這個分頁屬性. 于是手動實現(xiàn)了一個.



關鍵字

cocos2dx, CCScrollView, page, UIScrollView

基礎知識

在常見的圖形引擎中, 滑動組件的定義里有兩個重要的概念

  • viewSize: 這個大小值得是組件占用屏幕的大小. 即實際大小.
  • contentSize: 這個大小是一個虛擬的大小. 我們之所以要滾動, 必然是因為需要展示的內(nèi)容比現(xiàn)實的屏幕空間大. 我們需要滾動屏幕, 才能瀏覽到所有的顯示內(nèi)容. 這個contentSize即是我們虛擬出來的, 需要展示的所有內(nèi)容加起來的大小.
  • 分頁: 最典型的例子就是iphone的主界面. 我們不能任意指定一個位置, 讓滑動固定在那里. 它要么停留在第一頁, 要么停留在第二頁, 不會是第0.5頁. 每一頁的大小是viewSize決定的. 那么總頁數(shù)就是total_page_count = ceil(viewSize / contentSize )

CCScrollView源碼查看

我們知道, cocos2dx的觸摸都是通過CCTouchDelegate來實現(xiàn)的. 如果對cocos2dx的touch機制不熟悉的, 可以參考博客.

簡單介紹ccTouchBegan方法的功能:

ccTouchBegancocos2dxtouch機制的第一個方法. 這個方法的接口如下:

bool CCScrollView::ccTouchBegan(CCTouch* touch, CCEvent* event)

返回的bool值, 告訴cocos2dx中touch事件的管理者CCTouchDispatcher, 當前組件是否處理這一次觸摸:

  • 如果返回true, 則CCTouchDispatcher會根據(jù)用戶的touch動作, 在后續(xù)調(diào)用本組件的ccTouchMoved, ccTouchEnded, ccTouchCancelled方法.
  • 如果返回false, 則表示當前組件不處理此次touch事件. 后續(xù)的三個方法不會被調(diào)用.

CCScrollView::ccTouchBegan()解析

無碼無真相, 先貼一張代碼圖:

bool CCScrollView::ccTouchBegan(CCTouch* touch, CCEvent* event){    //tag-1    if (!this->isVisible())    {        return false;    }    //tag-2    CCRect frame = getViewRect();    //dispatcher does not know about clipping. reject touches outside visible bounds.    if (m_pTouches->count() > 2 ||        m_bTouchMoved          ||        !frame.containsPoint(m_pContainer->convertToWorldSpace(m_pContainer->convertTouchToNodeSpace(touch))))    {        return false;    }    ...    //tag-3    if (m_pTouches->count() == 1)    { // scrolling        m_tTouchPoint     = this->convertTouchToNodeSpace(touch);        m_bTouchMoved     = false;        m_bDragging     = true; //dragging started        m_tScrollDistance = ccp(0.0f, 0.0f);        m_fTouchLength    = 0.0f;    }    //tag-4    else if (m_pTouches->count() == 2)    {        ...        m_bDragging  = false;    }     return true;}

我把跟本博文主題關系不大的代碼用省略號(…)代替了. 下面是相關代碼解釋:

  • tag-1 當此組件隱藏的時候, 不予處理.
  • tag-2 當此觸摸點數(shù)大于2或者觸摸點不在當前組件的顯示范圍內(nèi)的時候, 不予處理.
  • tag-3 這是我們的重點. 當觸摸點數(shù)等于1的時候, 處理滑動操作.
  • tag-4 觸摸點等于2的時候, 響應縮放處理.

源代碼的修改

變量申明及方法增加

CCScrollView.h文件中增加以下成員變量和方法:

//CCScrollView.hpublic:    bool isPaged(){ return m_bPaged; };    void setPaged( bool value ){ m_bPaged = value; };PRotected:    clock_t m_touchBeganTime;    int     m_touchBeganOffset;    int     m_targetPage;    int     m_currPage;    float   m_pageAccSpeed;    float   m_distanceRatioOfTurn;    bool    m_bPaged;    void __pageTouchBegan();    //在CCScrollView的滑動被觸發(fā)的時候調(diào)用    bool __pageTouchEnd();      //在ScrollView的滑動停止的時候調(diào)用    void __pageTouchCancel();   //在滑動被取消的時候調(diào)用    void __pageClearTouch();    //在一次滑動結(jié)束的時候調(diào)用

方法的實現(xiàn):

四個方法的代碼可能要占用一些篇幅, 所以在這里, 先簡要講一下原理:

  1. 在touch開始的時候, 記錄一下當時時間m_touchBeganTime和開始滑動的位置m_touchBeganOffset.
  2. 在touch結(jié)束的時候, 獲取結(jié)束時刻的時間和位置. 我們有兩個標準來判斷應該翻頁還是停留在上一頁:
    • 如果滑動距離超過一頁距離的一半(或者是其他閾值),那么判斷為用戶希望翻到下一頁(或上一頁)
    • 如果滑動速度超過一個閾值, 那么判斷為用戶希望翻到下一頁(或上一頁)
  3. 當做了判斷之后, 即可滑動到對應的位置.

下面是四個方法的實現(xiàn), 實現(xiàn)了上述原理.

void CCScrollView::__pageTouchBegan(){    //僅在設置了分頁屬性, 并且只有一個滑動方向的時候, 才支持分頁.    if( !m_bPaged || ( m_eDirection != kCCScrollViewDirectionHorizontal && m_eDirection != kCCScrollViewDirectionVertical )) return ;    //記錄初試時間和位置    m_touchBeganTime = clock();    m_touchBeganOffset = m_eDirection == kCCScrollViewDirectionHorizontal ? getContentOffset().x : getContentOffset().y;}bool CCScrollView::__pageTouchEnd(){    if( !m_bPaged || ( m_eDirection != kCCScrollViewDirectionHorizontal && m_eDirection != kCCScrollViewDirectionVertical )) return false ;    //constant    const float PAGE_DISTENCE = m_eDirection == kCCScrollViewDirectionHorizontal ? getViewSize().width : getViewSize().height ;    if( PAGE_DISTENCE <= 0 ) return false;    const float MAX_PAGE = ( m_eDirection == kCCScrollViewDirectionHorizontal ? getContentSize().width : getContentSize().height ) / PAGE_DISTENCE;    const float MIN_PAGE = 0;    float currOffset = m_eDirection == kCCScrollViewDirectionHorizontal ? getContentOffset().x : getContentOffset().y;    float deltaOffset = -(currOffset - m_touchBeganOffset);    clock_t currTime = clock();    float speed =  currTime != m_touchBeganTime ? deltaOffset / ( currTime - m_touchBeganTime ) : 0;    m_targetPage = m_currPage;    if( abs(deltaOffset) >= TURN_PAGE_MIN_OFFSET_RATIO*PAGE_DISTENCE )    {//滑動距離大于某一閾值.        if( deltaOffset > 0 )        {            m_targetPage = m_currPage + 1;        }        else if( deltaOffset < 0 )        {            m_targetPage = m_currPage - 1;        }    }    else if( abs(speed) >= TURN_PAGE_SPEED )    {//速度大于某一閾值.        if( speed > 0 )        {            m_targetPage = m_currPage + 1;        }        else if( speed < 0 )        {            m_targetPage = m_currPage - 1;        }    }    if( m_targetPage > MAX_PAGE ) m_targetPage = MAX_PAGE;    else if( m_targetPage < MIN_PAGE ) m_targetPage = MIN_PAGE;    float targetOffset = -m_targetPage*( m_eDirection == kCCScrollViewDirectionHorizontal ? getViewSize().width : getViewSize().height );    float pageDurateion = 0.5;    CCPoint targetPointOffset = m_eDirection == kCCScrollViewDirectionHorizontal ? ccp( targetOffset, getContentOffset().y ) : ccp(getContentOffset().x, targetOffset );    setContentOffsetInDuration(targetPointOffset, pageDurateion);    m_currPage = m_targetPage;    return true;}void CCScrollView::__pageTouchCancel(){    if( !m_bPaged || ( m_eDirection != kCCScrollViewDirectionHorizontal && m_eDirection != kCCScrollViewDirectionVertical )) return ;    __pageClearTouch();}void CCScrollView::__pageClearTouch(){    //clear所有狀態(tài)    m_touchBeganOffset = 0;    m_touchBeganTime = 0;    m_targetPage = m_currPage;}

修改后的CCScrollView.h, CCScrollView.cpp

這里是修改后的文件, 可以直接下載覆蓋.
CCScrollView.zip
注意:上述代碼僅在cocos2dx-2.2.2cocos2dx-2.2.1版本上驗證通過. 其他版本請根據(jù)上述原理做適當?shù)男薷膥~~

Written with StackEdit.


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 游戏| 绥芬河市| 浦城县| 远安县| 邢台市| 东乌| 西华县| 图木舒克市| 噶尔县| 西丰县| 郑州市| 张家川| 广平县| 尼勒克县| 荃湾区| 麻江县| 江永县| 延庆县| 夹江县| 龙井市| 大邑县| 铁力市| 牙克石市| 哈巴河县| 武平县| 上犹县| 资阳市| 永春县| 福安市| 新建县| 丽水市| 新巴尔虎左旗| 刚察县| 大方县| 邹平县| 宁河县| 灌阳县| 华坪县| 新泰市| 汉川市| 龙州县|