diff --git a/cocos/ui/UIScrollView.cpp b/cocos/ui/UIScrollView.cpp index 6f4f9e657b..f5817534fe 100644 --- a/cocos/ui/UIScrollView.cpp +++ b/cocos/ui/UIScrollView.cpp @@ -116,6 +116,20 @@ void ScrollView::onEnter() scheduleUpdate(); } +void ScrollView::onExit() +{ +#if CC_ENABLE_SCRIPT_BINDING + if (_scriptType == kScriptTypeJavascript) + { + if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnExit)) + return; + } +#endif + + Layout::onExit(); + stopOverallScroll(); +} + bool ScrollView::init() { if (Layout::init()) @@ -482,12 +496,54 @@ void ScrollView::startAutoScroll(const Vec2& deltaMove, float timeInSec, bool at } } +void ScrollView::stopScroll() +{ + if (_scrolling) + { + if (_verticalScrollBar != nullptr) + { + _verticalScrollBar->onTouchEnded(); + } + if (_horizontalScrollBar != nullptr) + { + _horizontalScrollBar->onTouchEnded(); + } + + _scrolling = false; + _bePressed = false; + + startBounceBackIfNeeded(); + + dispatchEvent(SCROLLVIEW_EVENT_SCROLLING_ENDED, EventType::SCROLLING_ENDED); + } +} + void ScrollView::stopAutoScroll() { - _autoScrolling = false; - _autoScrollAttenuate = true; - _autoScrollTotalTime = 0; - _autoScrollAccumulatedTime = 0; + if (_autoScrolling) + { + if (_verticalScrollBar != nullptr) + { + _verticalScrollBar->onTouchEnded(); + } + if (_horizontalScrollBar != nullptr) + { + _horizontalScrollBar->onTouchEnded(); + } + + _autoScrolling = false; + _autoScrollAttenuate = true; + _autoScrollTotalTime = 0; + _autoScrollAccumulatedTime = 0; + + dispatchEvent(SCROLLVIEW_EVENT_AUTOSCROLL_ENDED, EventType::AUTOSCROLL_ENDED); + } +} + +void ScrollView::stopOverallScroll() +{ + stopScroll(); + stopAutoScroll(); } bool ScrollView::isNecessaryAutoScrollBrake() @@ -900,6 +956,9 @@ void ScrollView::handlePressLogic(Touch* /*touch*/) void ScrollView::handleMoveLogic(Touch *touch) { + if (!_bePressed) + return; + Vec3 currPt, prevPt; if(!calculateCurrAndPrevTouchPoints(touch, &currPt, &prevPt)) { @@ -915,6 +974,9 @@ void ScrollView::handleMoveLogic(Touch *touch) void ScrollView::handleReleaseLogic(Touch *touch) { + if (!_bePressed) + return; + // Gather the last touch information when released { Vec3 currPt, prevPt; diff --git a/cocos/ui/UIScrollView.h b/cocos/ui/UIScrollView.h index 0ea5cd2c5a..2f6646a400 100644 --- a/cocos/ui/UIScrollView.h +++ b/cocos/ui/UIScrollView.h @@ -160,11 +160,21 @@ public: */ Layout* getInnerContainer()const; + /** + * Immediately stops inner container scroll (auto scrolling is not affected). + */ + virtual void stopScroll(); + /** * Immediately stops inner container scroll initiated by any of the "scrollTo*" member functions */ virtual void stopAutoScroll(); + /** + * Immediately stops inner container scroll if any. + */ + virtual void stopOverallScroll(); + /** * Scroll inner container to bottom boundary of scrollview. * @param timeInSec Time in seconds. @@ -569,6 +579,11 @@ public: */ virtual void onEnter() override; + /** + * @lua NA + */ + virtual void onExit() override; + /** * When a widget is in a layout, you could call this method to get the next focused widget within a specified direction. * If the widget is not in a layout, it will return itself diff --git a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.cpp b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.cpp index d6b9146595..a1092c512d 100644 --- a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.cpp +++ b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.cpp @@ -15,6 +15,7 @@ UIScrollViewTests::UIScrollViewTests() ADD_TEST_CASE(UIScrollViewDisableTest); ADD_TEST_CASE(UIScrollViewInnerSize); ADD_TEST_CASE(UIScrollViewTestEvents); + ADD_TEST_CASE(UIScrollViewStopScrollingTest); } // UIScrollViewTest_Vertical @@ -684,8 +685,10 @@ bool UIScrollViewInnerSize::init() return false; } +// UIScrollViewTestEvents + UIScrollViewTestEvents::UIScrollViewTestEvents() -: _displayValueLabel(nullptr) + : _displayValueLabel(nullptr) { } @@ -762,3 +765,131 @@ bool UIScrollViewTestEvents::init() return false; } +// UIScrollViewStopScrollingTest + +UIScrollViewStopScrollingTest::UIScrollViewStopScrollingTest() + : _displayValueLabel(nullptr) + , _scrollView(nullptr) + , _remainingTime(0.0f) +{ + +} + +bool UIScrollViewStopScrollingTest::init() +{ + if (UIScene::init()) + { + Size widgetSize = _widget->getContentSize(); + + // Add a label in which the time remaining till scrolling stop will be displayed. + _displayValueLabel = Text::create("Scrolling stop isn't scheduled", "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.5f)); + _uiLayer->addChild(_displayValueLabel); + + // Add the alert + Text* alert = Text::create("Click the button and start to scroll", "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 = static_cast(root->getChildByName("background_Panel")); + + // Create the dragpanel + _scrollView = ui::ScrollView::create(); + _scrollView->setDirection(ui::ScrollView::Direction::BOTH); + _scrollView->setTouchEnabled(true); + _scrollView->setBounceEnabled(true); + _scrollView->setBackGroundImageScale9Enabled(true); + _scrollView->setBackGroundImage("cocosui/green_edit.png"); + _scrollView->setContentSize(Size(210, 122.5)); + _scrollView->setScrollBarWidth(4); + _scrollView->setScrollBarPositionFromCorner(Vec2(6, 6)); + Size backgroundSize = background->getContentSize(); + _scrollView->setPosition(Vec2((widgetSize.width - backgroundSize.width) / 2.0f + + (backgroundSize.width - _scrollView->getContentSize().width) / 2.0f, + (widgetSize.height - backgroundSize.height) / 2.0f + + (backgroundSize.height - _scrollView->getContentSize().height) / 2.0f)); + ImageView* imageView = ImageView::create("Hello.png"); + _scrollView->addChild(imageView); + _scrollView->setInnerContainerSize(imageView->getContentSize()); + Size innerSize = _scrollView->getInnerContainerSize(); + imageView->setPosition(Vec2(innerSize.width / 2.0f, innerSize.height / 2.0f)); + _uiLayer->addChild(_scrollView); + + // Log some ScrollView events. + _scrollView->addEventListener([&] (Ref*, ui::ScrollView::EventType e) + { + switch (e) + { + case ui::ScrollView::EventType::SCROLLING_BEGAN: + CCLOG("scrolling began!"); + break; + case ui::ScrollView::EventType::SCROLLING_ENDED: + CCLOG("scrolling ended!"); + break; + case ui::ScrollView::EventType::AUTOSCROLL_ENDED: + CCLOG("auto-scrolling ended!"); + break; + default: break; + } + }); + + // Jump to right bottom + _scrollView->jumpToBottomRight(); + + // Add button that will schedule scrolling stop when it is clicked. + Button* button_scale9 = Button::create("cocosui/button.png", "cocosui/buttonHighlighted.png"); + button_scale9->setTitleText("Stop scrolling in 3 sec."); + button_scale9->setScale9Enabled(true); + button_scale9->setContentSize(Size(120.0f, button_scale9->getVirtualRendererSize().height)); + button_scale9->setPosition(Vec2(innerSize.width / 2.0f, innerSize.height / 2.0f)); + button_scale9->addClickEventListener([this] (Ref*) { this->_remainingTime = 3.0f; }); + _scrollView->addChild(button_scale9); + + // Schedule update for this scene. + Director::getInstance()->getScheduler()->scheduleUpdate(this, 0, false); + + return true; + } + + return false; +} + +void UIScrollViewStopScrollingTest::update(float dt) +{ + UIScene::update(dt); + + if (_remainingTime > 0.0f) + { + _remainingTime -= dt; + + if (_remainingTime > 0.0f) + { + // Update timer caption. + char strRemainingTime[100]; + sprintf(strRemainingTime, "Stop scrolling in %.1f sec.", _remainingTime); + _displayValueLabel->setString(std::string(strRemainingTime)); + } + else + { + _scrollView->stopOverallScroll(); + + // Update timer caption. + std::string strRemainingTime = "Scrolling stop isn't scheduled"; + _displayValueLabel->setString(strRemainingTime); + + // Show hint label. + auto hintLabel = Label::createWithTTF("Stopped!", "fonts/Marker Felt.ttf", 32.0f); + Size contentSize = _uiLayer->getContentSize(); + hintLabel->setPosition(Vec2(contentSize.width / 2.0f, contentSize.height / 2.0f)); + hintLabel->runAction(Spawn::createWithTwoActions( + FadeOut::create(0.3f), + ScaleTo::create(0.3f, 2.0f) + )); + _uiLayer->addChild(hintLabel); + } + } +} diff --git a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.h b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.h index 3f1694adf9..694d996a77 100644 --- a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.h +++ b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.h @@ -167,4 +167,21 @@ protected: cocos2d::ui::Text* _displayValueLabel; }; + +class UIScrollViewStopScrollingTest : public UIScene +{ +public: + CREATE_FUNC(UIScrollViewStopScrollingTest); + + UIScrollViewStopScrollingTest(); + virtual bool init() override; + + virtual void update(float dt) override; + +protected: + + cocos2d::ui::Text* _displayValueLabel; + cocos2d::ui::ScrollView* _scrollView; + float _remainingTime; +}; #endif /* defined(__TestCpp__UIScrollViewTest__) */