CCScrollView添加滚动条和滚动背景

来源:互联网 发布:淘宝分销网址 编辑:程序博客网 时间:2024/05/08 12:49

cocos2d-X里提供的CCScrollView里并没有提供滚动条和滚动条背景,我对它进行了一些修改,所用的cocos2d-x 版本为3.0



使用方法

   CCBarScrollView* scrollView = CCBarScrollView::create();    scrollView->initWithViewSize((Size(280.0f,150.0f)));    scrollView->setContentSize(Size(280,150*10.0f));    scrollView->setDirection(cocos2d::extension::ScrollView::Direction::VERTICAL);    scrollView->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));    scrollView->setBounceable(true);    this->addChild(scrollView,0);        auto bgImage = Scale9Sprite::create("bg_pd_item.png");    auto barImage = Scale9Sprite::create("bg2.png");        scrollView->setBarImage(bgImage, barImage);//    scrollView->setAutoHidden(true);        for (int i = 0; i < 50; i++) {        auto sprite1 = Sprite::create("CloseNormal.png");        sprite1->setPosition(20, 20+i*40);        scrollView->addChild(sprite1);    }

控件代码:点击打开链接


class CCBarScrollView:public ScrollView{public:    static CCBarScrollView* create(Size size, Node* container = NULL);    static CCBarScrollView* create();                using Node::addChild;    void setBarImage(Scale9Sprite* barBg,Scale9Sprite* barImage);    virtual void addChild(Node * child, int zOrder, int tag) override;            void setContentOffset(Point offset, bool animated = false);        void setAutoHidden(bool autoHidden); //设置是否自动隐藏        virtual bool onTouchBegan(Touch *touch, Event *event);    virtual void onTouchEnded(Touch *touch, Event *event);protected:        void deaccelerateScrolling(float dt);    void updateBarPos();    Scale9Sprite* barBg;       //滚动条背景    Scale9Sprite* barImage;    //滚动条    bool isAutoHidden;         //滚动条是否自动隐藏};


设置滚动条背景和滚动条

void CCBarScrollView::setBarImage(Scale9Sprite* barBg, Scale9Sprite* barImage){        Size contentSize = this->getContentSize();    auto layer1 = LayerColor::create(Color4B(255, 0, 255, 255), contentSize.width, contentSize.height);    layer1->setCascadeColorEnabled(false);    layer1->setPosition( Point(0, 0));    this->addChild(layer1);        Size viewSize = this->getViewSize();    this->barBg = barBg;        this->barBg->setContentSize(Size(20,viewSize.height));    this->barBg->setPosition(Point(viewSize.width - 10,viewSize.height/2));    this->barImage = barImage;    Layer::addChild(this->barBg);    Layer::addChild(this->barImage);        this->barImage->setContentSize(Size(20,viewSize.height*(viewSize.height/contentSize.height)));        this->updateBarPos();}


设置滚动条是否自动隐藏

void CCBarScrollView::setAutoHidden(bool autoHidden){    this->isAutoHidden = autoHidden;        if(this->barImage != nullptr && this->isAutoHidden == true)    {        this->barImage->setVisible(false);    }}

在父类里,addChild会把子节点加入滚动container里面,但是滚动条和背景应该都在它的父节点上,所以要重载次方法

void CCBarScrollView::addChild(Node *child, int zOrder, int tag){    if (_container != child && barBg != child && barImage != child)    {        _container->addChild(child, zOrder, tag);    } else    {        Layer::addChild(child, zOrder, tag);    }}

在contentOffset发生改变的时候,需要更新滚动条的位置

void CCBarScrollView::setContentOffset(Point offset, bool animated/* = false*/){    if (animated)    { //animate scrolling        this->setContentOffsetInDuration(offset, BOUNCE_DURATION);    }    else    { //set the container position directly        if (!_bounceable)        {            const Point minOffset = this->minContainerOffset();            const Point maxOffset = this->maxContainerOffset();                        offset.x = MAX(minOffset.x, MIN(maxOffset.x, offset.x));            offset.y = MAX(minOffset.y, MIN(maxOffset.y, offset.y));        }                _container->setPosition(offset);                if (_delegate != NULL)        {            _delegate->scrollViewDidScroll(this);        }    }    this->updateBarPos();//    CCLOG("CCBarScrollView::setContentOffset");}

更新滚动条的位置函数

void CCBarScrollView::updateBarPos(){//    Point currentOffset = this->_container->getPosition();    Point currentOffset = this->getContentOffset();    Size contentSize = this->getContentSize();    Size viewSize = this->getViewSize();        Size barSize = this->barImage->getContentSize();    Point p =Point(viewSize.width-10,barSize.height/2 + viewSize.height*(-currentOffset.y/contentSize.height));   //    CCLOG("barImage %f,%f,%f,%f",p.x,p.y,barSize.width,barSize.height);//    CCLOG("currentOffset %f",currentOffset.y);    if(p.y < barSize.height/2)    {        p.y = barSize.height/2;    }    else if(p.y + barSize.height/2 > viewSize.height)    {        p.y = viewSize.height- barSize.height/2;    }        this->barImage->setPosition(p);}

滚动条在点击松开的时候,会做减速的运动,所以也要在减速函数做相应的处理

void CCBarScrollView::deaccelerateScrolling(float dt){    if (_dragging)    {        this->unschedule(schedule_selector(CCBarScrollView::deaccelerateScrolling));        return;    }        float newX, newY;    Point maxInset, minInset;        _container->setPosition(_container->getPosition() + _scrollDistance);        if (_bounceable)    {        maxInset = _maxInset;        minInset = _minInset;    }    else    {        maxInset = this->maxContainerOffset();        minInset = this->minContainerOffset();    }        newX = _container->getPosition().x;    newY = _container->getPosition().y;        _scrollDistance     = _scrollDistance * SCROLL_DEACCEL_RATE;    this->setContentOffset(Point(newX,newY));        if ((fabsf(_scrollDistance.x) <= SCROLL_DEACCEL_DIST &&         fabsf(_scrollDistance.y) <= SCROLL_DEACCEL_DIST) ||        newY >= maxInset.y || newY <= minInset.y ||        newX >= maxInset.x || newX <= minInset.x)    {                if(this->isAutoHidden)        {            FiniteTimeAction *faseOut;            faseOut = FadeOut::create(0.2);            this->barImage->runAction(faseOut);        }        this->unschedule(schedule_selector(CCBarScrollView::deaccelerateScrolling));        this->relocateContainer(true);    }            this->updateBarPos();}

点击事件开始和结束的处理

bool CCBarScrollView::onTouchBegan(Touch* touch, Event* event){    if (!this->isVisible())    {        return false;    }            Rect frame = getViewRect();        //dispatcher does not know about clipping. reject touches outside visible bounds.    if (_touches.size() > 2 ||        _touchMoved          ||        !frame.containsPoint(touch->getLocation()))    {        CCLOG("outside visible bounds.");        return false;    }        if (std::find(_touches.begin(), _touches.end(), touch) == _touches.end())    {        _touches.push_back(touch);        //        CCLOG("_touches.push_back");    }        if (_touches.size() == 1)    { // scrolling        _touchPoint     = this->convertTouchToNodeSpace(touch);        _touchMoved     = false;        _dragging     = true; //dragging started        _scrollDistance = Point(0.0f, 0.0f);        _touchLength    = 0.0f;                if(isAutoHidden)        {            FiniteTimeAction *faseIn;            faseIn = FadeIn::create(0.2);            this->barImage->setVisible(true);            this->barImage->setOpacity(0);            this->barImage->runAction(faseIn);        }                //        CCLOG("scrolling");    }    else if (_touches.size() == 2)    {        _touchPoint = (this->convertTouchToNodeSpace(_touches[0]).getMidpoint(                                                                              this->convertTouchToNodeSpace(_touches[1])));                _touchLength = _container->convertTouchToNodeSpace(_touches[0]).getDistance(                                                                                    _container->convertTouchToNodeSpace(_touches[1]));                _dragging  = false;        this->barImage->setVisible(false);        //        CCLOG("_dragging");    }    return true;}

void CCBarScrollView::onTouchEnded(Touch* touch, Event* event){    if (!this->isVisible())    {        return;    }        auto touchIter = std::find(_touches.begin(), _touches.end(), touch);    bool isDeaccelerateScrolling = false;    if (touchIter != _touches.end())    {        if (_touches.size() == 1 && _touchMoved)        {            isDeaccelerateScrolling = true;            this->schedule(schedule_selector(CCBarScrollView::deaccelerateScrolling));        }        _touches.erase(touchIter);    }        if (_touches.size() == 0)    {        if(this->isAutoHidden && isDeaccelerateScrolling == false)        {            FiniteTimeAction *faseOut;            faseOut = FadeOut::create(0.2);            this->barImage->runAction(faseOut);        }        _dragging = false;        _touchMoved = false;    }}


0 0
原创粉丝点击