zoukankan      html  css  js  c++  java
  • cocos2dx

    接上一节内容: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

  • 相关阅读:
    MySql和oracle的不同
    Session的有效期设置
    WebSocket和WebRtc的一些心得
    Spring事务管理
    Tomcat下使用war包发布项目
    Log4j记日志功能
    javascript typeof和instanceof
    js模块化的意义
    有关call和apply的理解。
    h5滑动插件(包含幻灯片滑动逻辑)
  • 原文地址:https://www.cnblogs.com/stratrail/p/5084737.html
Copyright © 2011-2022 走看看