cocos2dx - 控件擴展之pageview循環顯示


接上一節內容:cocos2dx - shader實現任意動畫的殘影效果

 本節主要講一下擴展PageView控件功能

  在實際游戲應用中,經常會碰到用原來的控件難以實現的功能。這時候就需要根據需求,通過選擇合適的控件進行方便的擴展來實現。

擴展控件一般是通過對原來的控件進行繼承來實現,這樣可以很好的應用原來的屬性及方法,同時可以方便的添加自己需要的方法及屬性。

 

例子:實現對pageview進行循環翻頁效果。

分析:

  1、翻頁方法有2個方式,滑動翻頁及點擊按鈕左右翻動。

  2、在觸發翻頁后需要移動頁面位置保持當前新的選中頁面在中間。

  3、每次翻頁后需要觸發事件,實現更新內容。

實現:

1、為了優化顯示,我們不在一開始創建所有頁面,僅創建3個layout來存儲顯示的內容,然后在翻頁觸發后刷新頁面內容。

    Layout* m_pLeftLayout;
    Layout* m_pRightLayout;
    Layout* m_pCurLayout;

2、同時重寫覆蓋以下幾個方法,來實現移動頁面的判斷。

    
    void scrollToPage(ssize_t idx) ; 
    
    virtual bool scrollPages(Vec2 touchOffset) override;

    virtual void handleMoveLogic(Touch *touch) override;

    virtual void handleReleaseLogic(Touch *touch) override;
    
    void movePages(Vec2 offset);

主要是通過判斷移動的方向,來判斷需要更新的下一個頁面。然后在移動了一定比例的頁面距離后(0.75),將下一個頁面設為當前界面,重設對應左右界面。
代碼如下:

void CCyclePageView::movePages(Vec2 offset)
{
    if (!m_pCurLayout || !m_pRightLayout || !m_pLeftLayout)
    {
        return;
    }
    m_pCurLayout->setPosition(m_pCurLayout->getPosition() + offset);
    m_pRightLayout->setPosition(m_pRightLayout->getPosition() + offset);
    m_pLeftLayout->setPosition(m_pLeftLayout->getPosition() + offset);
    Size size = getContentSize();
    switch (_touchMoveDirection)
    {
    case TouchDirection::LEFT: // left 
        if (m_pCurLayout->getPositionX()<-size.width*0.75)
        {

            Layout* newRight = m_pLeftLayout;
            newRight->setPositionX(m_pRightLayout->getPositionX() + size.width);
            m_pLeftLayout = m_pCurLayout;
            m_pCurLayout = m_pRightLayout;
            m_pRightLayout = newRight;

            ++_curPageIdx;
            UpdateShowLayout(_curPageIdx, m_pCurLayout,true);
        }

        break;
    case TouchDirection::RIGHT: // right 
        if (m_pCurLayout->getPositionX()>size.width*0.75)
        {
            Layout* newLeft = m_pRightLayout;
            newLeft->setPositionX(m_pLeftLayout->getPositionX() - size.width);
            m_pRightLayout = m_pCurLayout;
            m_pCurLayout = m_pLeftLayout;
            m_pLeftLayout = newLeft;
            
            --_curPageIdx;
            UpdateShowLayout(_curPageIdx, m_pCurLayout, true);
        }
        break;
    case TouchDirection::UP:
        if (m_pCurLayout->getPositionY()>size.width*0.75)
        {
            Layout* newLeft = m_pRightLayout;
            newLeft->setPositionX(m_pLeftLayout->getPositionX() - size.height);
            m_pRightLayout = m_pCurLayout;
            m_pCurLayout = m_pLeftLayout;
            m_pLeftLayout = newLeft;
            --_curPageIdx;
            UpdateShowLayout(_curPageIdx, m_pCurLayout, true);
        }
        break;
    case TouchDirection::DOWN:
        if (m_pCurLayout->getPositionY()<-size.height*0.75)
        {
            Layout* newRight = m_pLeftLayout;
            newRight->setPositionX(m_pRightLayout->getPositionX() + size.height);
            m_pLeftLayout = m_pCurLayout;
            m_pCurLayout = m_pRightLayout;
            m_pRightLayout = newRight;
            ++_curPageIdx;
            UpdateShowLayout(_curPageIdx, m_pCurLayout, true);
        }
        break;
    default:
        break;
    }
    if (_curPageIdx<0)
    {
        _curPageIdx = m_nPageSize-1;
    }
    if (_curPageIdx >= m_nPageSize)
    {
        _curPageIdx = 0;
    }
}

3、通過以下幾個方法實現更新界面顯示

    Layout* GetCurPage(){ return m_pCurLayout;}

    void addPageChangedListener(const std::function<void(Layout*, size_t)> callback){ m_callback = callback; }

    void UpdateShowLayout(ssizs_t nCurIdx, Layout* layout, bool isForceCallBack=false);

在UpdateshowLayout中將傳入待更新的頁面更新內容為nCurIdx的內容,這里通過Tag標識來判斷。若Tag與待顯示的Idx不一致則通過addPageChangedListener中設置的回調來實現更新。

void CCyclePageView::UpdateShowLayout(ssize_t nCurIdx, Layout* layout,bool isForceCallBack)
{
    if (nCurIdx<0)
    {
        nCurIdx = m_nPageSize - 1;
    }
    if (nCurIdx >= m_nPageSize)
    {
        nCurIdx = 0;
    }
    if (layout && (isForceCallBack || layout->getTag() != nCurIdx))
    { 
        layout->setTag(nCurIdx);
        if (m_callback)
        {
            m_callback(layout,nCurIdx);
        }
    }
}

這里的 isForceCallBack 用來在void movePages(Vec2 offset)中實現最后更新的一個頁面為當前選中的頁面。 

使用:

1、在創建后,通過SetPageSize設置循環頁面個數,並通過addPageChangedListener中添加頁面變化監聽。

2、翻頁使用scrollToPage()翻到指定頁面,或者直接通過拖動控件活動實現。

3、在監聽中必須添加更新顯示效果。

            CCyclePageView* pNewPageView = CCyclePageView::create();
            pNewPageView->addPageChangedListener(std::bind(&CMainWnd::onPageViewUpdate, this, std::placeholders::_1, std::placeholders::_2));
            pNewPageView->setDirection(cocos2d::ui::PageView::Direction::HORIZONTAL);
            pNewPageView->SetPageSize(nCount);
            pNewPageView->scrollToPage(0);

完整代碼地址:https://github.com/mydishes/cocos2dx-Ex/tree/master/CyclePageView


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM