cocos2dx - 控件扩展之pageview循环显示(转)

原文:点击打开链接


本节主要讲一下扩展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/Steaphans/cocos2dx-Ex/tree/master/CyclePageView


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
cocos2dx-lua中,可以使用ScrollView显示可视区域的内容,以提高游戏性能。实现方式如下: 1. 创建一个ScrollView,并设置其大小和位置。 ```lua local scrollView = ccui.ScrollView:create() scrollView:setContentSize(cc.size(500, 500)) scrollView:setPosition(cc.p(0, 0)) ``` 2. 设置ScrollView的滚动方向和滚动条位置。 ```lua scrollView:setDirection(ccui.ScrollViewDir.vertical) scrollView:setScrollBarPositionFromCorner(cc.p(7, 7)) ``` 3. 创建一个容器,用于存储要加载的内容。 ```lua local container = ccui.Layout:create() container:setContentSize(cc.size(500, 1000)) scrollView:addChild(container) ``` 4. 定义一个函数,用于加载每一项内容到容器中。 ```lua local function loadItem(index) local item = ccui.Text:create() item:setString("Item " .. index) item:setPosition(cc.p(250, 1000 - index * 50)) container:addChild(item) end ``` 5. 在ScrollView的回调函数中,根据滚动位置动态加载内容,并移除不在可视区域的内容项。 ```lua local function scrollViewEvent(sender, eventType) if eventType == ccui.ScrollviewEventType.scrolling then local pos = scrollView:getInnerContainer():getPosition() local top = scrollView:getContentSize().height local bottom = top - scrollView:getInnerContainerSize().height for i = container:getChildrenCount(), 1, -1 do local item = container:getChildren()[i] local itemPos = item:convertToWorldSpace(cc.p(0, 0)) if itemPos.y < 0 or itemPos.y > top then item:removeFromParent() end end if pos.y < bottom + 500 then for i = 1, 10 do loadItem(i) end end end end scrollView:addScrollViewEventListener(scrollViewEvent) ``` 这样,在滚动ScrollView时,只会显示可视区域内的内容,不在可视区域内的内容会被自动移除。通过移除不需要显示的内容项,可以避免ScrollView中的内容过多导致游戏卡顿。可以根据实际需求调整每次加载的内容数量和内容项的布局样式,以及移除不需要显示的内容项的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值