From 5f34c1f0727528be99dedb41aa2192da50921eba Mon Sep 17 00:00:00 2001 From: andyque Date: Sat, 1 Aug 2015 18:18:46 +0800 Subject: [PATCH] add PageView vertical scroll support --- .../js-bindings/script/ccui/jsb_cocos2d_ui.js | 6 +- .../lua-bindings/script/ui/GuiConstants.lua | 5 + cocos/ui/UIPageView.cpp | 232 ++++++++++++++---- cocos/ui/UIPageView.h | 41 +++- .../UIPageViewTest/UIPageViewTest.cpp | 95 +++++++ .../UIPageViewTest/UIPageViewTest.h | 16 ++ 6 files changed, 336 insertions(+), 59 deletions(-) diff --git a/cocos/scripting/js-bindings/script/ccui/jsb_cocos2d_ui.js b/cocos/scripting/js-bindings/script/ccui/jsb_cocos2d_ui.js index 5c29e5352b..772230c7e5 100644 --- a/cocos/scripting/js-bindings/script/ccui/jsb_cocos2d_ui.js +++ b/cocos/scripting/js-bindings/script/ccui/jsb_cocos2d_ui.js @@ -249,6 +249,10 @@ ccui.PageView.EVENT_TURNING = 0; ccui.PageView.TOUCH_DIR_LEFT = 0; ccui.PageView.TOUCH_DIR_RIGHT = 1; +//PageView direction +ccui.PageView.DIRECTION_HORIZONTAL = 0; +ccui.PageView.DIRECTION_VERTICAL = 1; + /* * UIButton */ @@ -500,4 +504,4 @@ if (ccui.VideoPlayer) */ ccui.Widget.prototype.addNode = ccui.Widget.prototype.addChild; ccui.Widget.prototype.getSize = ccui.Widget.prototype.getContentSize; -ccui.Widget.prototype.setSize = ccui.Widget.prototype.setContentSize; \ No newline at end of file +ccui.Widget.prototype.setSize = ccui.Widget.prototype.setContentSize; diff --git a/cocos/scripting/lua-bindings/script/ui/GuiConstants.lua b/cocos/scripting/lua-bindings/script/ui/GuiConstants.lua index c3bd2b50cf..43d6e450e0 100644 --- a/cocos/scripting/lua-bindings/script/ui/GuiConstants.lua +++ b/cocos/scripting/lua-bindings/script/ui/GuiConstants.lua @@ -161,6 +161,11 @@ ccui.PageViewEventType = { turning = 0, } +ccui.PageViewDirection = { + HORIZONTAL = 0, + VERTICAL = 1 +} + ccui.PVTouchDir = { touchLeft = 0, touchRight = 1, diff --git a/cocos/ui/UIPageView.cpp b/cocos/ui/UIPageView.cpp index 62e4c1ec2c..cd6ff6e81d 100644 --- a/cocos/ui/UIPageView.cpp +++ b/cocos/ui/UIPageView.cpp @@ -35,6 +35,7 @@ _isAutoScrolling(false), _autoScrollDistance(0.0f), _autoScrollSpeed(0.0f), _autoScrollDirection(AutoScrollDirection::LEFT), +_direction(Direction::HORIZONTAL), _curPageIdx(-1), _touchMoveDirection(TouchDirection::LEFT), _leftBoundaryChild(nullptr), @@ -230,11 +231,23 @@ float PageView::getPositionXByIndex(ssize_t idx)const { return (getContentSize().width * (idx-_curPageIdx)); } + +float PageView::getPositionYByIndex(ssize_t idx)const +{ + return (getContentSize().height * (idx-_curPageIdx)); +} void PageView::onSizeChanged() { Layout::onSizeChanged(); - _rightBoundary = getContentSize().width; + if (_direction == Direction::HORIZONTAL) + { + _rightBoundary = getContentSize().width; + } + else + { + _rightBoundary = getContentSize().height; + } _doLayoutDirty = true; } @@ -265,12 +278,26 @@ void PageView::updateAllPagesPosition() // If the layout is dirty, don't trigger auto scroll _isAutoScrolling = false; - float pageWidth = getContentSize().width; - for (int i=0; isetPosition(Vec2((i-_curPageIdx) * pageWidth, 0)); - + float pageWidth = getContentSize().width; + for (int i=0; isetPosition(Vec2((i-_curPageIdx) * pageWidth, 0)); + + } + + } + else if(_direction == Direction::VERTICAL) + { + float pageHeight = getContentSize().height; + for (int i=0; isetPosition(Vec2(0,(i-_curPageIdx) * pageHeight)); + + } } } @@ -292,11 +319,43 @@ void PageView::scrollToPage(ssize_t idx) } _curPageIdx = idx; Layout* curPage = _pages.at(idx); - _autoScrollDistance = -(curPage->getPosition().x); + if (_direction == Direction::HORIZONTAL) + { + _autoScrollDistance = -(curPage->getPosition().x); + if (_autoScrollDistance > 0) + { + _autoScrollDirection = AutoScrollDirection::RIGHT; + } + else + { + _autoScrollDirection = AutoScrollDirection::LEFT; + } + } + else if(_direction == Direction::VERTICAL) + { + _autoScrollDistance = -(curPage->getPosition().y); + if (_autoScrollDistance > 0) + { + _autoScrollDirection = AutoScrollDirection::UP; + } + else + { + _autoScrollDirection = AutoScrollDirection::DOWN; + } + } _autoScrollSpeed = fabs(_autoScrollDistance)/0.2f; - _autoScrollDirection = _autoScrollDistance > 0 ? AutoScrollDirection::RIGHT : AutoScrollDirection::LEFT; _isAutoScrolling = true; } + +void PageView::setDirection(cocos2d::ui::PageView::Direction direction) +{ + this->_direction = direction; +} + +PageView::Direction PageView::getDirection()const +{ + return this->_direction; +} void PageView::update(float dt) { @@ -308,32 +367,30 @@ void PageView::update(float dt) void PageView::autoScroll(float dt) { + float step = _autoScrollSpeed*dt; + int sign = 1; switch (_autoScrollDirection) { case AutoScrollDirection::LEFT: + case AutoScrollDirection::DOWN: { - float step = _autoScrollSpeed*dt; if (_autoScrollDistance + step >= 0.0f) { step = -_autoScrollDistance; - _autoScrollDistance = 0.0f; _isAutoScrolling = false; + _autoScrollDistance = 0.0f; } else { _autoScrollDistance += step; } - scrollPages(-step); - if (!_isAutoScrolling) - { - pageTurningEvent(); - } + sign = -1; break; } break; case AutoScrollDirection::RIGHT: + case AutoScrollDirection::UP: { - float step = _autoScrollSpeed*dt; if (_autoScrollDistance - step <= 0.0f) { step = _autoScrollDistance; @@ -344,19 +401,25 @@ void PageView::autoScroll(float dt) { _autoScrollDistance -= step; } - scrollPages(step); - - if (!_isAutoScrolling) - { - pageTurningEvent(); - } - break; } default: break; } + + if (_direction == Direction::HORIZONTAL) + { + scrollPages(Vec2(step * sign, 0)); + } + else + { + scrollPages(Vec2(0, step * sign)); + } + if (!_isAutoScrolling) + { + pageTurningEvent(); + } } bool PageView::onTouchBegan(Touch *touch, Event *unusedEvent) @@ -409,16 +472,16 @@ void PageView::doLayout() _doLayoutDirty = false; } -void PageView::movePages(float offset) +void PageView::movePages(Vec2 offset) { for (auto& page : this->getPages()) { - page->setPosition(Vec2(page->getPosition().x + offset, - page->getPosition().y)); + Vec2 oldPosition = page->getPosition(); + page->setPosition(oldPosition + offset); } } -bool PageView::scrollPages(float touchOffset) +bool PageView::scrollPages(Vec2 touchOffset) { if (this->getPageCount() <= 0) { @@ -430,29 +493,49 @@ bool PageView::scrollPages(float touchOffset) return false; } - float realOffset = touchOffset; + Vec2 realOffset = touchOffset; switch (_touchMoveDirection) { case TouchDirection::LEFT: // left - - if (_rightBoundaryChild->getRightBoundary() + touchOffset <= _rightBoundary) + if (_rightBoundaryChild->getRightBoundary() + touchOffset.x <= _rightBoundary) { - realOffset = _rightBoundary - _rightBoundaryChild->getRightBoundary(); + realOffset.x = _rightBoundary - _rightBoundaryChild->getRightBoundary(); + realOffset.y = 0; movePages(realOffset); return false; } break; case TouchDirection::RIGHT: // right - - if (_leftBoundaryChild->getLeftBoundary() + touchOffset >= _leftBoundary) + if (_leftBoundaryChild->getLeftBoundary() + touchOffset.x >= _leftBoundary) { - realOffset = _leftBoundary - _leftBoundaryChild->getLeftBoundary(); + realOffset.x = _leftBoundary - _leftBoundaryChild->getLeftBoundary(); + realOffset.y = 0; movePages(realOffset); return false; } break; + case TouchDirection::UP: + { + if (_leftBoundaryChild->getBottomBoundary() + touchOffset.y >= _leftBoundary) + { + realOffset.y = _leftBoundary - _leftBoundaryChild->getBottomBoundary(); + realOffset.x = 0; + movePages(realOffset); + return false; + } + }break; + case TouchDirection::DOWN: + { + if (_rightBoundaryChild->getTopBoundary() + touchOffset.y <= _rightBoundary) + { + realOffset.y = _rightBoundary - _rightBoundaryChild->getTopBoundary(); + realOffset.x = 0; + movePages(realOffset); + return false; + } + }break; default: break; } @@ -466,17 +549,34 @@ void PageView::handleMoveLogic(Touch *touch) { Vec2 touchPoint = touch->getLocation(); - float offset = 0.0; - offset = touchPoint.x - touch->getPreviousLocation().x; - - if (offset < 0) + Vec2 offset; + offset = touchPoint - touch->getPreviousLocation(); + + if (_direction == Direction::HORIZONTAL) { - _touchMoveDirection = TouchDirection::LEFT; + if (offset.x < 0) + { + _touchMoveDirection = TouchDirection::LEFT; + } + else if (offset.x > 0) + { + _touchMoveDirection = TouchDirection::RIGHT; + } + offset.y = 0; } - else if (offset > 0) + else { - _touchMoveDirection = TouchDirection::RIGHT; + offset.x = 0; + if(offset.y < 0) + { + _touchMoveDirection = TouchDirection::DOWN; + } + else if(offset.y > 0) + { + _touchMoveDirection = TouchDirection::UP; + } } + scrollPages(offset); } @@ -513,28 +613,48 @@ void PageView::handleReleaseLogic(Touch *touch) { Vec2 curPagePos = curPage->getPosition(); ssize_t pageCount = this->getPageCount(); - float curPageLocation = curPagePos.x; - float pageWidth = getContentSize().width; - if (!_usingCustomScrollThreshold) { - _customScrollThreshold = pageWidth / 2.0; + + auto contentSize = getContentSize(); + if (!_usingCustomScrollThreshold) + { + if (_direction == Direction::HORIZONTAL) + { + _customScrollThreshold = contentSize.width / 2.0; + } + else if(_direction == Direction::VERTICAL) + { + _customScrollThreshold = contentSize.height / 2.0; + } } float boundary = _customScrollThreshold; - if (curPageLocation <= -boundary) + float moveBoundray = 0.0f; + if (_direction == Direction::HORIZONTAL) + { + curPagePos.y = 0; + moveBoundray = curPagePos.x; + } + else + { + curPagePos.x = 0; + moveBoundray = curPagePos.y; + } + + if (moveBoundray <= -boundary) { if (_curPageIdx >= pageCount-1) { - scrollPages(-curPageLocation); + scrollPages(curPagePos); } else { scrollToPage(_curPageIdx+1); } } - else if (curPageLocation >= boundary) + else if (moveBoundray >= boundary) { if (_curPageIdx <= 0) { - scrollPages(-curPageLocation); + scrollPages(curPagePos); } else { @@ -560,11 +680,18 @@ void PageView::interceptTouchEvent(TouchEventType event, Widget *sender, Touch * _touchBeganPosition = touch->getLocation(); _isInterceptTouch = true; } - break; + break; case TouchEventType::MOVED: { float offset = 0; - offset = fabs(sender->getTouchBeganPosition().x - touchPoint.x); + if (_direction == Direction::HORIZONTAL) + { + offset = fabs(sender->getTouchBeganPosition().x - touchPoint.x); + } + else if(_direction == Direction::VERTICAL) + { + offset = fabs(sender->getTouchBeganPosition().y - touchPoint.y); + } _touchMovePosition = touch->getLocation(); if (offset > _childFocusCancelOffset) { @@ -572,7 +699,7 @@ void PageView::interceptTouchEvent(TouchEventType event, Widget *sender, Touch * handleMoveLogic(touch); } } - break; + break; case TouchEventType::CANCELED: case TouchEventType::ENDED: { @@ -666,6 +793,7 @@ void PageView::copySpecialProperties(Widget *widget) _pageViewEventSelector = pageView->_pageViewEventSelector; _usingCustomScrollThreshold = pageView->_usingCustomScrollThreshold; _customScrollThreshold = pageView->_customScrollThreshold; + _direction = pageView->_direction; } } diff --git a/cocos/ui/UIPageView.h b/cocos/ui/UIPageView.h index a894595462..e0bbe602d8 100644 --- a/cocos/ui/UIPageView.h +++ b/cocos/ui/UIPageView.h @@ -53,7 +53,7 @@ typedef void (Ref::*SEL_PageViewEvent)(Ref*, PageViewEventType); #define pagevieweventselector(_SELECTOR)(SEL_PageViewEvent)(&_SELECTOR) /** - *@brief Layout manager that allows the user to flip left and right through pages of data. + *@brief Layout manager that allows the user to flip left & right and up & down through pages of data. * */ class CC_GUI_DLL PageView : public Layout @@ -76,7 +76,15 @@ public: enum class TouchDirection { LEFT, - RIGHT + RIGHT, + UP, + DOWN + }; + + enum class Direction + { + HORIZONTAL, + VERTICAL }; /** @@ -141,7 +149,24 @@ public: * @param index A given index. */ void removePageAtIndex(ssize_t index); - + + /** + * Changes scroll direction of PageView + * + * @see `Direction` + * @param direction Scroll direction enum. + * @since v3.8 + */ + void setDirection(Direction direction); + + /** + * Query scroll direction of PageView. + * + * @see `Direction` + * @since v3.8 + * @return PageView scroll direction. + */ + Direction getDirection()const; /** * @brief Remove all pages of the PageView. @@ -247,11 +272,12 @@ protected: Layout* createPage(); float getPositionXByIndex(ssize_t idx)const; + float getPositionYByIndex(ssize_t idx)const; ssize_t getPageCount()const; void updateBoundaryPages(); - virtual bool scrollPages(float touchOffset); - void movePages(float offset); + virtual bool scrollPages(Vec2 touchOffset); + void movePages(Vec2 offset); void pageTurningEvent(); void updateAllPagesSize(); void updateAllPagesPosition(); @@ -273,12 +299,15 @@ protected: enum class AutoScrollDirection { LEFT, - RIGHT + RIGHT, + UP, + DOWN }; bool _isAutoScrolling; float _autoScrollDistance; float _autoScrollSpeed; AutoScrollDirection _autoScrollDirection; + Direction _direction; ssize_t _curPageIdx; Vector _pages; diff --git a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.cpp b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.cpp index 315007d8b7..1d5f6be49f 100644 --- a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.cpp +++ b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.cpp @@ -12,6 +12,7 @@ UIPageViewTests::UIPageViewTests() ADD_TEST_CASE(UIPageViewTouchPropagationTest); ADD_TEST_CASE(UIPageViewDynamicAddAndRemoveTest); ADD_TEST_CASE(UIPageViewJumpToPageTest); + ADD_TEST_CASE(UIPageViewVerticalTest); } // UIPageViewTest @@ -808,3 +809,97 @@ bool UIPageViewJumpToPageTest::init() } return false; } + +// UIPageViewVerticalTest +UIPageViewVerticalTest::UIPageViewVerticalTest() +: _displayValueLabel(nullptr) +{ + +} + +UIPageViewVerticalTest::~UIPageViewVerticalTest() +{ +} + +bool UIPageViewVerticalTest::init() +{ + if (UIScene::init()) + { + Size widgetSize = _widget->getContentSize(); + + // Add a label in which the dragpanel events will be displayed + _displayValueLabel = Text::create("Move by Vertical direction", "fonts/Marker Felt.ttf", 32); + _displayValueLabel->setAnchorPoint(Vec2(0.5f, -1.0f)); + _displayValueLabel->setPosition(Vec2(widgetSize.width / 2.0f, + widgetSize.height / 2.0f + + _displayValueLabel->getContentSize().height * 1.5)); + _uiLayer->addChild(_displayValueLabel); + + // Add the black background + Text* alert = Text::create("PageView", "fonts/Marker Felt.ttf", 30); + alert->setColor(Color3B(159, 168, 176)); + alert->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); + _uiLayer->addChild(alert); + + Layout* root = static_cast(_uiLayer->getChildByTag(81)); + + Layout* background = dynamic_cast(root->getChildByName("background_Panel")); + + // Create the page view + PageView* pageView = PageView::create(); + pageView->setContentSize(Size(240.0f, 130.0f)); + Size backgroundSize = background->getContentSize(); + pageView->setPosition(Vec2((widgetSize.width - backgroundSize.width) / 2.0f + + (backgroundSize.width - pageView->getContentSize().width) / 2.0f, + (widgetSize.height - backgroundSize.height) / 2.0f + + (backgroundSize.height - pageView->getContentSize().height) / 2.0f)); + pageView->setDirection(ui::PageView::Direction::VERTICAL); + + pageView->removeAllPages(); + + int pageCount = 4; + for (int i = 0; i < pageCount; ++i) + { + Layout* layout = Layout::create(); + layout->setContentSize(Size(240.0f, 130.0f)); + + ImageView* imageView = ImageView::create("cocosui/scrollviewbg.png"); + imageView->setScale9Enabled(true); + imageView->setContentSize(Size(240, 130)); + imageView->setPosition(Vec2(layout->getContentSize().width / 2.0f, layout->getContentSize().height / 2.0f)); + layout->addChild(imageView); + + Text* label = Text::create(StringUtils::format("page %d",(i+1)), "fonts/Marker Felt.ttf", 30); + label->setColor(Color3B(192, 192, 192)); + label->setPosition(Vec2(layout->getContentSize().width / 2.0f, layout->getContentSize().height / 2.0f)); + layout->addChild(label); + + pageView->insertPage(layout,i); + } + + pageView->addEventListener(CC_CALLBACK_2(UIPageViewVerticalTest::pageViewEvent, this)); + + _uiLayer->addChild(pageView); + + return true; + } + return false; +} + +void UIPageViewVerticalTest::pageViewEvent(Ref *pSender, PageView::EventType type) +{ + switch (type) + { + case PageView::EventType::TURNING: + { + PageView* pageView = dynamic_cast(pSender); + + _displayValueLabel->setString(StringUtils::format("page = %ld", pageView->getCurPageIndex() + 1)); + } + break; + + default: + break; + } +} + diff --git a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.h b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.h index c3555efcea..2dc68dbcc9 100644 --- a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.h +++ b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.h @@ -126,4 +126,20 @@ protected: cocos2d::ui::Text* _displayValueLabel; }; +class UIPageViewVerticalTest : public UIScene +{ +public: + CREATE_FUNC(UIPageViewVerticalTest); + + UIPageViewVerticalTest(); + ~UIPageViewVerticalTest(); + virtual bool init() override; + + void pageViewEvent(cocos2d::Ref* sender, cocos2d::ui::PageView::EventType type); + +protected: + + cocos2d::ui::Text* _displayValueLabel; +}; + #endif /* defined(__TestCpp__UIPageViewTest__) */