首页 > 代码库 > 实现滑动屏幕与底层滑动指标适配

实现滑动屏幕与底层滑动指标适配

首先是封装好的滑动指标类,具体首先创建一个画图类:SliderIndicator类,该类代码如下:

//SliderIndicator.h
#include "cocos2d.h"
#include "ui/CocosGUI.h"

USING_NS_CC;

class SliderIndicator:public ui::Layout
{

public:
    
    CREATE_FUNC(SliderIndicator);
    
    virtual bool init();
 
    CC_SYNTHESIZE(Color4B, _circleColor, CircleColor);//使用CC_SYNTHESIZE设置绘制颜色
    
    
protected:
    
    //参考之前文章介绍draw函数
    void onDraw(const Mat4 &transform, bool transformUpdated);
    void draw(Renderer *renderer, const Mat4 &transform, bool transformUpdated);
    
    CustomCommand _customCommand;
};
//SliderIndicator.cpp
#include "SliderIndicator.h"
bool SliderIndicator::init()
{
    bool bRet = false;
    do {
        CC_BREAK_IF(!ui::Layout::init());
      
        bRet = true;
    } while (0);
    return bRet;
}

void SliderIndicator::draw(Renderer *renderer, const Mat4 &transform, bool transformUpdated)
{ 
    _customCommand.init(_globalZOrder);
    _customCommand.func = CC_CALLBACK_0(SliderIndicator::onDraw, this,transform,transformUpdated);
    renderer->addCommand(&_customCommand);   
}

void SliderIndicator::onDraw(const cocos2d::Mat4 &transform, bool transformUpdated)
{
    //OpenGL设置
    Director* director = Director::getInstance();
    CCASSERT(nullptr != director, "Director is null when seting matrix stack");
    director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);
    //CC_SYNTHESIZE设置_circleColor
    DrawPrimitives::setDrawColor4B(_circleColor.r, _circleColor.g, _circleColor.b, _circleColor.a);
    //绘制实心圆点
    DrawPrimitives::drawSolidCircle( Vec2(0,0), director->getWinSize().height / 130, CC_DEGREES_TO_RADIANS(90), 50, 1.0f, 1.0f);
    
    //end draw
    director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}

然后根据滑动指标个数,创建SliderIndicatorLayout类,代码如下:

//SliderIndicator.h
#include "cocos2d.h"
#include "ui/CocosGUI.h"

USING_NS_CC;

class SliderIndicatorLayout:public ui::Layout
{
    
public:
    
    CREATE_FUNC(SliderIndicatorLayout);
    
    virtual bool init();
    //添加指示圆点个数
    void addIndicator(int num);
    //选中的第几个
    void changeIndicator(int index);
       
private:
    Size winSize;
    float radius;    
};


//SliderIndicatorLayout.cpp
#include "SliderIndicatorLayout.h"
#include "SliderIndicator.h"


bool SliderIndicatorLayout::init()
{
    bool bRet = false;
    do {
        CC_BREAK_IF(!ui::Layout::init());
        
        setLayoutType(cocos2d::ui::Layout::Type::VERTICAL);
        winSize = Director::getInstance()->getWinSize();
        //设置每个滑动指标大小
        radius = winSize.height / 130;
        
        bRet = true;
    } while (0);
    return bRet;
}

void SliderIndicatorLayout::addIndicator(int num)
{
    setSize(Size(radius * 2, radius*3 * num));
    for (int i = 0 ; i < num; i++)
    {
        auto indicator = SliderIndicator::create();
        indicator->setSize(Size(radius, radius));
        indicator->setCircleColor(Color4B(255, 40, 255, 255));//CC_SYNTHESIZE
        indicator->setTag(i);//设置Tag,便于以后获取,来改变滑动指标
        addChild(indicator);
        //设置相对布局,由于项目的需要,该处设置的是垂直布局,在HelloWorld中setRotation(-90),将其旋转
        auto lp_indicator = ui::LinearLayoutParameter::create();
        lp_indicator->setGravity(cocos2d::ui::LinearLayoutParameter::LinearGravity::TOP);
        lp_indicator->setMargin(ui::Margin(0,radius * 2.0f,0,0));
        if (i == 0)
        {
             lp_indicator->setMargin(ui::Margin(0, 0,0,0));
            
        }
        indicator->setLayoutParameter(lp_indicator);
        
    }
    changeIndicator(0);//默认是第一个滑动指标
}

void SliderIndicatorLayout::changeIndicator(int index)//改变选中的滑动指标
{
    for (int i = 0; i < getChildren().size(); i++)
    {
        auto indicator = dynamic_cast<SliderIndicator*>(getChildByTag(i));//根据Tag获取滑动指标
        indicator->setCircleColor(Color4B(93, 114, 123, 95));
        if (i == index)
        {
            indicator->setCircleColor(Color4B(93, 114, 123, 225));//改变颜色即可
        }
        
    }
}

使用方法:

1、创建HelloWorld类

在HelloWorld类中创建SliderIndicatorLayout类,通过addIndicator()函数传入滑动指标个数;

2、在SliderIndicatorLayout类中addIndicator设置SliderIndicator的颜色、滑动指标个数,即可调用SliderIndicator类完成绘制圆点;

3、执行SliderIndicator中的draw和ondraw函数;具体实现可参看TestCpp函数

4、在HelloWorld中通过事件响应,执行changeIndicator()函数,即可完成滑动指标的切换;


HelloWorld类使用:

//HelloWorld.h
#include "cocos2d.h"
#include "cocos2d.h"
#include "SliderIndicatorLayout.h"
#include "ui/CocosGUI.h"
using namespace cocos2d::ui;
USING_NS_CC;

class HelloWorld : public cocos2d::Layer
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  
    
    SliderIndicatorLayout* sliderIndicator;
    // a selector callback
    void menuCloseCallback(cocos2d::Ref* pSender);
    void pageViewEvent(Ref *pSender, cocos2d::ui::PageView::EventType type);//PageView事件
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
};

//HelloWorld.cpp
#include "HelloWorldScene.h"
#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include "SliderIndicatorLayout.h"

using namespace cocos2d::ui;
USING_NS_CC;

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    
	closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));

    // create menu, it's an autorelease object
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);
//创建PageView
    auto pageView = PageView::create();
    pageView->addEventListener(CC_CALLBACK_2(HelloWorld::pageViewEvent, this));//pageView事件
//    pageView->setLayoutType(cocos2d::ui::Layout::Type::RELATIVE);
//    pageView->setBackGroundColorType(ui::Layout::BackGroundColorType::SOLID);
//    pageView->setBackGroundColor(Color3B::BLACK);
    pageView->ignoreAnchorPointForPosition(false);
    pageView->setAnchorPoint(Vec2(0.5, 0.5));
    pageView->setSize(Size(visibleSize.width/2,visibleSize.height/2));
    pageView->setPosition(Vec2(visibleSize.width/2, visibleSize.height/2));
    
//    auto rp_pageView = RelativeLayoutParameter::create();
//    rp_pageView->setAlign(RelativeLayoutParameter::RelativeAlign::CENTER_IN_PARENT);
//    pageView->setLayoutParameter(rp_pageView);
//  增加4个page    
    for(int i = 0; i < 4; i++)
    {
        Layout* layout1 = Layout::create();
        layout1->setSize(Size(visibleSize.width/2,visibleSize.height/2));
        
        ImageView* imageView = ImageView::create("scrollviewbg.png");
        imageView->setScale9Enabled(true);
        imageView->setSize(Size(visibleSize.width, visibleSize.height));
        imageView->setPosition(Point(layout1->getSize().width / 2, layout1->getSize().height / 2));
        layout1->addChild(imageView);
        
        //设置page内容
        
        Text* label = Text::create(StringUtils::format("page %d",(i+1)), "fonts/Marker Felt.ttf", 30);
        label->setColor(Color3B(92, 192, 192));
        label->setPosition(Point(layout1->getSize().width / 2.0f, layout1->getSize().height / 2.0f));
        layout1->addChild(label);
        pageView->addPage(layout1);
    }
    addChild(pageView);
    //创建滑动指标
    sliderIndicator = SliderIndicatorLayout::create();
    sliderIndicator->retain();
    sliderIndicator->addIndicator(4);//传入个数函数
    sliderIndicator->ignoreAnchorPointForPosition(false);
    sliderIndicator->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
    sliderIndicator->setPosition(Vec2(visibleSize.width/2,100));
    sliderIndicator->setRotation(-90);
    addChild(sliderIndicator);
    
//    auto rp_slider = ui::RelativeLayoutParameter::create();
//    rp_slider->setAlign(cocos2d::ui::RelativeLayoutParameter::RelativeAlign::CENTER_IN_PARENT);
//    sliderIndicator->setLayoutParameter(rp_slider);
    
    
    return true;
}

void HelloWorld::pageViewEvent(cocos2d::Ref *pSender, cocos2d::ui::PageView::EventType type)
{
    auto pageView = dynamic_cast<PageView*>(pSender);//获取当前页面
    auto index = pageView->getCurPageIndex();//获取当前页面的index
    switch (type)
    {
        case cocos2d::ui::PageView::EventType::TURNING:
        {
            sliderIndicator->changeIndicator(index);//根据page的index改变滑动指标
        }
        break;
        
        
        default:
        break;
    }
}


void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
	MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif

    Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

执行效果如下: