// // PurchaseBannerView.cpp // merge6 // // Created by Black Homles on 2024/9/23. // #include "PurchaseBannerView.hpp" PurchaseBannerView* PurchaseBannerView::create(Size& viewSize, sDotCfg& dotCfg, bool cachePages,bool isHor) { PurchaseBannerView* ret = new PurchaseBannerView(); ret->init(viewSize, dotCfg, cachePages, isHor); ret->autorelease(); return ret; } void PurchaseBannerView::setDelegate(PurchaseBannerViewDelegate* delegate) { _pageViewDelegate = delegate; } void PurchaseBannerView::init(Size& viewSize, sDotCfg& dotCfg, bool cachePages, bool isHor) { Layer::init(); _dotCfg = dotCfg; _viewSize = viewSize; _cachePages = cachePages; _isHori = isHor; _currentPageIndex = 0; _pageCount = 0; this->setContentSize(_viewSize); //get scrollview _scrollView = cocos2d::extension::ScrollView::create(); _scrollView->setViewSize(_viewSize); if (isHor) { _scrollView->setDirection(cocos2d::extension::ScrollView::Direction::HORIZONTAL); } else { _scrollView->setDirection(cocos2d::extension::ScrollView::Direction::VERTICAL); } _scrollView->setBounceable(false); _scrollView->setDelegate(this); this->addChild(_scrollView); auto listener = EventListenerTouchOneByOne::create(); listener->setSwallowTouches(true); listener->onTouchBegan = CC_CALLBACK_2(PurchaseBannerView::onTouchBegan,this); listener->onTouchMoved = CC_CALLBACK_2(PurchaseBannerView::onTouchMoved,this); listener->onTouchEnded = CC_CALLBACK_2(PurchaseBannerView::onTouchEnded,this); listener->onTouchCancelled = CC_CALLBACK_2(PurchaseBannerView::onTouchCancelled,this); Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,this); } void PurchaseBannerView::_initDotInd() { if (!_initedDot) { _initedDot = true; if (_dotCfg.sepWidth != 0) { int sepWidth = _dotCfg.sepWidth; int yStart = _dotCfg.yStart; auto tmpSp = Sprite::createWithSpriteFrameName(_dotCfg.normalSp); int contentWidth = tmpSp->getContentSize().width; int xStart = (_viewSize.width - _pageCount * contentWidth - (_pageCount - 1) * sepWidth) / 2; for (int i = 0; i < _pageCount; i++) { tmpSp = Sprite::createWithSpriteFrameName(_dotCfg.normalSp); tmpSp->setPosition(Vec2(xStart + i * (contentWidth + sepWidth), yStart)); this->addChild(tmpSp, 1); _dotSpArr.push_back(tmpSp); } _updateIndSp(); } } } void PurchaseBannerView::_initDotAdded() { if (_dotSpArr.size() < _pageCount && _dotCfg.sepWidth != 0) { int sepWidth = _dotCfg.sepWidth; int yStart = _dotCfg.yStart; auto tmpSp = Sprite::createWithSpriteFrameName(_dotCfg.normalSp); int contentWidth = tmpSp->getContentSize().width; int xStart = (_viewSize.width - _pageCount * contentWidth - (_pageCount - 1) * sepWidth) / 2; for (int i = (int)_dotSpArr.size(); i < _pageCount; i++) { tmpSp = Sprite::createWithSpriteFrameName(_dotCfg.normalSp); tmpSp->setPosition(Vec2(xStart + i * (contentWidth + sepWidth), yStart)); this->addChild(tmpSp, 1); _dotSpArr.push_back(tmpSp); } for (int i = 0; i < _dotSpArr.size(); i++) { tmpSp = _dotSpArr[i]; tmpSp->setPosition(Vec2(xStart + i * (contentWidth + sepWidth), yStart)); } _updateIndSp(); } } void PurchaseBannerView::_updateIndSp() { if (_dotSpArr.size() > 0) { for (int i = 0; i < _pageCount; i++) { string spname = i == _currentPageIndex ? _dotCfg.highSp : _dotCfg.normalSp; _dotSpArr[i]->setSpriteFrame(spname); } } } void PurchaseBannerView::_resizeView() { if (_scrollView == nullptr) { return; } if (_isHori) { _scrollView->setContentSize(Size(_viewSize.width * _pageCount, _viewSize.height)); _scrollView->setContentOffset(Vec2(-_currentPageIndex * _viewSize.width, 0)); } else { _scrollView->setContentSize(Size(_viewSize.width, _viewSize.height * _pageCount)); _scrollView->getContainer()->setPositionY(-_viewSize.height * (_pageCount - 1)); _scrollView->setContentOffset(Vec2(0, -(_pageCount - 1 - _currentPageIndex) * _viewSize.height)); } } void PurchaseBannerView::onEnter() { Layer::onEnter(); _touchedCount = 0; _scrollView->setTouchEnabled(true); _scrollView->setSwallowTouches(false); } void PurchaseBannerView::onExit() { Layer::onExit(); //log("PageView ~ onExit"); } void PurchaseBannerView::addBanner(PurchaseBannerCell* tmpNode) { if (tmpNode == nullptr) { return; } _pageCount++; _currentPageIndex = 0; this->_resizeView(); int addInIdx = _pageCount - 1; if (_isHori) { tmpNode->setPositionX(_viewSize.width * addInIdx); } else { tmpNode->setPositionY(_viewSize.height * (_pageCount - addInIdx - 1)); } tmpNode->setAnchorPoint(Vec2(0,0)); _scrollView->getContainer()->addChild(tmpNode,0,addInIdx); tmpNode->setIdx(addInIdx); this->_initDotAdded(); } void PurchaseBannerView::reloadData(int pageCount, int defaultIndex) { _scrollView->getContainer()->removeAllChildren(); _currentPageIndex = defaultIndex; _pageCount = pageCount; this->_resizeView(); this->_generatePage(); if (_pageViewDelegate != nullptr) { _pageViewDelegate->onPageChanged(_currentPageIndex, defaultIndex > 0); } this->_initDotInd(); } void PurchaseBannerView::setCurrentPageIndex(int index) { if (index != _currentPageIndex && index >= 0 && index < _pageCount) { _currentPageIndex = index; this->_generatePage(); this->_removeExpirePage(); _scrollView->setContentOffset(Vec2(-_currentPageIndex * _viewSize.width, 0)); this->_notifyPageChanged(true); } } PurchaseBannerCell* PurchaseBannerView::getCurrentPage() { return dynamic_cast(_scrollView->getContainer()->getChildByTag(_currentPageIndex)); } int PurchaseBannerView::getCurrentPageIdx() { return _currentPageIndex; } void PurchaseBannerView::moveToPrePage() { if (_currentPageIndex > 0) { --_currentPageIndex; this->_beginNewMoveToAnimation(0); } } void PurchaseBannerView::moveToNextPage() { if (_currentPageIndex < _pageCount - 1) { ++_currentPageIndex; this->_beginNewMoveToAnimation(0); } } void PurchaseBannerView::moveReferToPageIndex(int delta) { if (delta > 0 && _currentPageIndex + delta < _pageCount - 1) { _currentPageIndex += delta; this->_beginNewMoveToAnimation(0); } else if (delta < 0 && delta + _currentPageIndex >= 0) { _currentPageIndex += delta; this->_beginNewMoveToAnimation(0); } } void PurchaseBannerView::moveToFirstPage() { _currentPageIndex = 0; this->_beginNewMoveToAnimation(0); } int PurchaseBannerView::getPageCount() { return _pageCount; } void PurchaseBannerView::_generatePage() { if (_pageViewDelegate == nullptr || _cachePages) { return; } for (int i = _currentPageIndex - 1; i <= _currentPageIndex + 1; i++) { if (i >= 0 && i < _pageCount) { PurchaseBannerCell* page = dynamic_cast(_scrollView->getContainer()->getChildByTag(i)); if (page == nullptr) { page = _pageViewDelegate->pageCellAtIndex(this, i); if (_isHori) { page->setPositionX(_viewSize.width * i); } else { page->setPositionY(_viewSize.height * (_pageCount - i - 1)); } _scrollView->getContainer()->addChild(page,0,i); page->setIdx(i); } } } } void PurchaseBannerView::_removeExpirePage() { if (_cachePages) { return; } int firstLeftPageIndex = _currentPageIndex - 2; int lastRightPageIndex = _currentPageIndex + 2; for (int i = 0; i <= firstLeftPageIndex; i++) { PurchaseBannerCell* page = dynamic_cast(_scrollView->getContainer()->getChildByTag(i)); if (page != nullptr) { _scrollView->getContainer()->removeChild(page); } } for (int i = lastRightPageIndex; i < _pageCount; i++) { PurchaseBannerCell* page = dynamic_cast(_scrollView->getContainer()->getChildByTag(i)); if (page != nullptr ) { _scrollView->getContainer()->removeChild(page); } } } void PurchaseBannerView::_beginNewMoveToAnimation(float dt) { _scrollView->unscheduleAllCallbacks(); _scrollView->getContainer()->stopAllActions(); if (_isHori) { _scrollView->setContentOffset(Vec2(-_currentPageIndex * _viewSize.width,0),true); } else { _scrollView->setContentOffset(Vec2(0,-(_pageCount - _currentPageIndex - 1) * _viewSize.height),true); } this->_generatePage(); this->_removeExpirePage(); auto thisnode = this; this->scheduleOnce([=](float dt){ thisnode->_notifyPageChanged(false); },0.18,"notifyPageChanged"); } void PurchaseBannerView::_notifyPageChanged(bool manualSet) { if (_pageViewDelegate != nullptr) { _pageViewDelegate->onPageChanged(_currentPageIndex, manualSet); } this->_updateIndSp(); this->_autoSetBounceable(); } void PurchaseBannerView::_autoSetBounceable() { if (_currentPageIndex == 0 || _currentPageIndex == _pageCount - 1) { _scrollView->setBounceable(true); } else { _scrollView->setBounceable(false); } } bool PurchaseBannerView::onTouchBegan(Touch* touch, Event* unused_event) { if (this->isTouchedInNode(this,touch)) { //log("PageView : onTouchBegan!"); if (this->isTouchedInNode(_scrollView,touch,true,_scrollView->getViewSize())) { _touchedCount++; if (_touchedCount == 1) { _touchBeganPoint = touch->getLocation(); this->_autoSetBounceable(); if (_pageViewDelegate != nullptr) { _pageViewDelegate->onPageTouchBegan(touch); } return true; } } } return false; } void PurchaseBannerView::onTouchEnded(Touch* touch, Event* unused_event) { //log("PageView - onTouchEnded"); Vec2 newPoint = touch->getLocation(); if (_scrollViewMoved) { bool autoScroll = false; if (_isHori) { if (newPoint.x > _touchBeganPoint.x && _currentPageIndex > 0) { //<- _currentPageIndex--; autoScroll = true; } else if (newPoint.x < _touchBeganPoint.x && _currentPageIndex < _pageCount - 1) { //-> _currentPageIndex++; autoScroll = true; } } else { if (newPoint.y < _touchBeganPoint.y && _currentPageIndex > 0) { //-/|\; _currentPageIndex--; autoScroll = true; } else if (newPoint.y > _touchBeganPoint.y && _currentPageIndex < _pageCount - 1) { //-\|/ _currentPageIndex++; autoScroll = true; } } if (autoScroll) { _scrollView->setBounceable(false); this->scheduleOnce(CC_SCHEDULE_SELECTOR(PurchaseBannerView::_beginNewMoveToAnimation),0); } _scrollViewMoved = false; } else if (_touchedCount == 1) { if (this->isTouchedInNode(_scrollView,touch,true,_scrollView->getViewSize())) { PurchaseBannerCell* page = dynamic_cast(_scrollView->getContainer()->getChildByTag(_currentPageIndex)); if (_pageViewDelegate != nullptr) { _pageViewDelegate->pageCellTouched(touch, page); } } } _touchedCount = 0; } void PurchaseBannerView::scrollViewDidScroll(cocos2d::extension::ScrollView* view) { _scrollViewMoved = _scrollView->isTouchMoved(); } bool PurchaseBannerView::isTouchedInNode(Node* node, Touch* touch, bool isAnotherSize, Vec2 anotherSize) { Size contentSize = Size::ZERO; if (isAnotherSize) { contentSize = Size(anotherSize.x,anotherSize.y); } else { contentSize = node->getContentSize(); } Vec2 pos = node->convertTouchToNodeSpace(touch); if (pos.x >= 0 && pos.x <= contentSize.width) { if (pos.y >= 0 && pos.y <= contentSize.height) { return true; } } return false; }