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; } }
CCScrollView添加滚动条和滚动背景
时间: 2024-10-23 08:21:53