Merge pull request #13152 from zilongshanren/addVerticalPageView

add PageView vertical scroll support
This commit is contained in:
pandamicro 2015-08-03 13:00:48 +08:00
commit 702e667143
6 changed files with 374 additions and 65 deletions

View File

@ -248,6 +248,12 @@ ccui.PageView.EVENT_TURNING = 0;
//PageView touch direction //PageView touch direction
ccui.PageView.TOUCH_DIR_LEFT = 0; ccui.PageView.TOUCH_DIR_LEFT = 0;
ccui.PageView.TOUCH_DIR_RIGHT = 1; ccui.PageView.TOUCH_DIR_RIGHT = 1;
ccui.PageView.TOUCH_DIR_UP = 2;
ccui.PageView.TOUCH_DIR_DOWN = 3;
//PageView direction
ccui.PageView.DIRECTION_HORIZONTAL = 0;
ccui.PageView.DIRECTION_VERTICAL = 1;
/* /*
* UIButton * UIButton
@ -500,4 +506,4 @@ if (ccui.VideoPlayer)
*/ */
ccui.Widget.prototype.addNode = ccui.Widget.prototype.addChild; ccui.Widget.prototype.addNode = ccui.Widget.prototype.addChild;
ccui.Widget.prototype.getSize = ccui.Widget.prototype.getContentSize; ccui.Widget.prototype.getSize = ccui.Widget.prototype.getContentSize;
ccui.Widget.prototype.setSize = ccui.Widget.prototype.setContentSize; ccui.Widget.prototype.setSize = ccui.Widget.prototype.setContentSize;

View File

@ -161,9 +161,16 @@ ccui.PageViewEventType = {
turning = 0, turning = 0,
} }
ccui.PageViewDirection = {
HORIZONTAL = 0,
VERTICAL = 1
}
ccui.PVTouchDir = { ccui.PVTouchDir = {
touchLeft = 0, touchLeft = 0,
touchRight = 1, touchRight = 1,
touchUp = 2,
touchDown = 3
} }
ccui.ListViewGravity = { ccui.ListViewGravity = {

View File

@ -35,6 +35,7 @@ _isAutoScrolling(false),
_autoScrollDistance(0.0f), _autoScrollDistance(0.0f),
_autoScrollSpeed(0.0f), _autoScrollSpeed(0.0f),
_autoScrollDirection(AutoScrollDirection::LEFT), _autoScrollDirection(AutoScrollDirection::LEFT),
_direction(Direction::HORIZONTAL),
_curPageIdx(-1), _curPageIdx(-1),
_touchMoveDirection(TouchDirection::LEFT), _touchMoveDirection(TouchDirection::LEFT),
_leftBoundaryChild(nullptr), _leftBoundaryChild(nullptr),
@ -230,11 +231,23 @@ float PageView::getPositionXByIndex(ssize_t idx)const
{ {
return (getContentSize().width * (idx-_curPageIdx)); return (getContentSize().width * (idx-_curPageIdx));
} }
float PageView::getPositionYByIndex(ssize_t idx)const
{
return (getContentSize().height * (idx-_curPageIdx));
}
void PageView::onSizeChanged() void PageView::onSizeChanged()
{ {
Layout::onSizeChanged(); Layout::onSizeChanged();
_rightBoundary = getContentSize().width; if (_direction == Direction::HORIZONTAL)
{
_rightBoundary = getContentSize().width;
}
else
{
_rightBoundary = getContentSize().height;
}
_doLayoutDirty = true; _doLayoutDirty = true;
} }
@ -265,12 +278,23 @@ void PageView::updateAllPagesPosition()
// If the layout is dirty, don't trigger auto scroll // If the layout is dirty, don't trigger auto scroll
_isAutoScrolling = false; _isAutoScrolling = false;
float pageWidth = getContentSize().width;
for (int i=0; i<pageCount; i++) for (int i=0; i<pageCount; i++)
{ {
Layout* page = _pages.at(i); Layout* page = _pages.at(i);
page->setPosition(Vec2((i-_curPageIdx) * pageWidth, 0)); Vec2 newPosition;
if (_direction == Direction::HORIZONTAL)
{
float pageWidth = getContentSize().width;
newPosition = Vec2((i-_curPageIdx) * pageWidth, 0);
}
else if(_direction == Direction::VERTICAL)
{
float pageHeight = getContentSize().height;
newPosition = Vec2(0,(i-_curPageIdx) * pageHeight * -1);
}
page->setPosition(newPosition);
} }
} }
@ -292,11 +316,43 @@ void PageView::scrollToPage(ssize_t idx)
} }
_curPageIdx = idx; _curPageIdx = idx;
Layout* curPage = _pages.at(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::DOWN;
}
else
{
_autoScrollDirection = AutoScrollDirection::UP;
}
}
_autoScrollSpeed = fabs(_autoScrollDistance)/0.2f; _autoScrollSpeed = fabs(_autoScrollDistance)/0.2f;
_autoScrollDirection = _autoScrollDistance > 0 ? AutoScrollDirection::RIGHT : AutoScrollDirection::LEFT;
_isAutoScrolling = true; _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) void PageView::update(float dt)
{ {
@ -308,32 +364,30 @@ void PageView::update(float dt)
void PageView::autoScroll(float dt) void PageView::autoScroll(float dt)
{ {
float step = _autoScrollSpeed*dt;
int sign = 1;
switch (_autoScrollDirection) switch (_autoScrollDirection)
{ {
case AutoScrollDirection::LEFT: case AutoScrollDirection::LEFT:
case AutoScrollDirection::UP:
{ {
float step = _autoScrollSpeed*dt;
if (_autoScrollDistance + step >= 0.0f) if (_autoScrollDistance + step >= 0.0f)
{ {
step = -_autoScrollDistance; step = -_autoScrollDistance;
_autoScrollDistance = 0.0f;
_isAutoScrolling = false; _isAutoScrolling = false;
_autoScrollDistance = 0.0f;
} }
else else
{ {
_autoScrollDistance += step; _autoScrollDistance += step;
} }
scrollPages(-step); sign = -1;
if (!_isAutoScrolling)
{
pageTurningEvent();
}
break; break;
} }
break; break;
case AutoScrollDirection::RIGHT: case AutoScrollDirection::RIGHT:
case AutoScrollDirection::DOWN:
{ {
float step = _autoScrollSpeed*dt;
if (_autoScrollDistance - step <= 0.0f) if (_autoScrollDistance - step <= 0.0f)
{ {
step = _autoScrollDistance; step = _autoScrollDistance;
@ -344,19 +398,25 @@ void PageView::autoScroll(float dt)
{ {
_autoScrollDistance -= step; _autoScrollDistance -= step;
} }
scrollPages(step);
if (!_isAutoScrolling)
{
pageTurningEvent();
}
break; break;
} }
default: default:
break; 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) bool PageView::onTouchBegan(Touch *touch, Event *unusedEvent)
@ -409,16 +469,16 @@ void PageView::doLayout()
_doLayoutDirty = false; _doLayoutDirty = false;
} }
void PageView::movePages(float offset) void PageView::movePages(Vec2 offset)
{ {
for (auto& page : this->getPages()) for (auto& page : this->getPages())
{ {
page->setPosition(Vec2(page->getPosition().x + offset, Vec2 oldPosition = page->getPosition();
page->getPosition().y)); page->setPosition(oldPosition + offset);
} }
} }
bool PageView::scrollPages(float touchOffset) bool PageView::scrollPages(Vec2 touchOffset)
{ {
if (this->getPageCount() <= 0) if (this->getPageCount() <= 0)
{ {
@ -430,29 +490,50 @@ bool PageView::scrollPages(float touchOffset)
return false; return false;
} }
float realOffset = touchOffset; Vec2 realOffset = touchOffset;
switch (_touchMoveDirection) switch (_touchMoveDirection)
{ {
case TouchDirection::LEFT: // left case TouchDirection::LEFT: // left
if (_rightBoundaryChild->getRightBoundary() + touchOffset.x <= _rightBoundary)
if (_rightBoundaryChild->getRightBoundary() + touchOffset <= _rightBoundary)
{ {
realOffset = _rightBoundary - _rightBoundaryChild->getRightBoundary(); realOffset.x = _rightBoundary - _rightBoundaryChild->getRightBoundary();
realOffset.y = 0;
movePages(realOffset); movePages(realOffset);
return false; return false;
} }
break; break;
case TouchDirection::RIGHT: // right case TouchDirection::RIGHT: // right
if (_leftBoundaryChild->getLeftBoundary() + touchOffset.x >= _leftBoundary)
if (_leftBoundaryChild->getLeftBoundary() + touchOffset >= _leftBoundary)
{ {
realOffset = _leftBoundary - _leftBoundaryChild->getLeftBoundary(); realOffset.x = _leftBoundary - _leftBoundaryChild->getLeftBoundary();
realOffset.y = 0;
movePages(realOffset); movePages(realOffset);
return false; return false;
} }
break; break;
case TouchDirection::UP:
{
if (_rightBoundaryChild->getBottomBoundary() + touchOffset.y >= _leftBoundary)
{
realOffset.y = _leftBoundary - _rightBoundaryChild->getBottomBoundary();
realOffset.x = 0;
movePages(realOffset);
return false;
}
}break;
case TouchDirection::DOWN:
{
if (_leftBoundaryChild->getTopBoundary() + touchOffset.y <= _rightBoundary)
{
realOffset.y = _rightBoundary - _leftBoundaryChild->getTopBoundary();
realOffset.x = 0;
movePages(realOffset);
return false;
}
}break;
default: default:
break; break;
} }
@ -466,17 +547,34 @@ void PageView::handleMoveLogic(Touch *touch)
{ {
Vec2 touchPoint = touch->getLocation(); Vec2 touchPoint = touch->getLocation();
float offset = 0.0; Vec2 offset;
offset = touchPoint.x - touch->getPreviousLocation().x; offset = touchPoint - touch->getPreviousLocation();
if (offset < 0) 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::UP;
}
else if(offset.y < 0)
{
_touchMoveDirection = TouchDirection::DOWN;
}
} }
scrollPages(offset); scrollPages(offset);
} }
@ -513,38 +611,88 @@ void PageView::handleReleaseLogic(Touch *touch)
{ {
Vec2 curPagePos = curPage->getPosition(); Vec2 curPagePos = curPage->getPosition();
ssize_t pageCount = this->getPageCount(); ssize_t pageCount = this->getPageCount();
float curPageLocation = curPagePos.x;
float pageWidth = getContentSize().width; auto contentSize = getContentSize();
if (!_usingCustomScrollThreshold) {
_customScrollThreshold = pageWidth / 2.0; float moveBoundray = 0.0f;
float scrollDistance;
if (_direction == Direction::HORIZONTAL)
{
curPagePos.y = 0;
moveBoundray = curPagePos.x;
scrollDistance = contentSize.width / 2.0;
}
else if(_direction == Direction::VERTICAL)
{
curPagePos.x = 0;
moveBoundray = curPagePos.y;
scrollDistance = contentSize.height / 2.0;
}
if (!_usingCustomScrollThreshold)
{
_customScrollThreshold = scrollDistance;
} }
float boundary = _customScrollThreshold; float boundary = _customScrollThreshold;
if (curPageLocation <= -boundary)
if (_direction == Direction::HORIZONTAL)
{ {
if (_curPageIdx >= pageCount-1) if (moveBoundray <= -boundary)
{ {
scrollPages(-curPageLocation); if (_curPageIdx >= pageCount-1)
{
scrollPages(curPagePos);
}
else
{
scrollToPage(_curPageIdx+1);
}
}
else if (moveBoundray >= boundary)
{
if (_curPageIdx <= 0)
{
scrollPages(curPagePos);
}
else
{
scrollToPage(_curPageIdx-1);
}
} }
else else
{ {
scrollToPage(_curPageIdx+1); scrollToPage(_curPageIdx);
} }
} }
else if (curPageLocation >= boundary) else if(_direction == Direction::VERTICAL)
{ {
if (_curPageIdx <= 0) if (moveBoundray >= boundary)
{ {
scrollPages(-curPageLocation); if (_curPageIdx >= pageCount-1)
{
scrollPages(curPagePos);
}
else
{
scrollToPage(_curPageIdx+1);
}
}
else if (moveBoundray <= -boundary)
{
if (_curPageIdx <= 0)
{
scrollPages(curPagePos);
}
else
{
scrollToPage(_curPageIdx-1);
}
} }
else else
{ {
scrollToPage(_curPageIdx-1); scrollToPage(_curPageIdx);
} }
} }
else
{
scrollToPage(_curPageIdx);
}
} }
} }
@ -560,11 +708,18 @@ void PageView::interceptTouchEvent(TouchEventType event, Widget *sender, Touch *
_touchBeganPosition = touch->getLocation(); _touchBeganPosition = touch->getLocation();
_isInterceptTouch = true; _isInterceptTouch = true;
} }
break; break;
case TouchEventType::MOVED: case TouchEventType::MOVED:
{ {
float offset = 0; 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(); _touchMovePosition = touch->getLocation();
if (offset > _childFocusCancelOffset) if (offset > _childFocusCancelOffset)
{ {
@ -572,7 +727,7 @@ void PageView::interceptTouchEvent(TouchEventType event, Widget *sender, Touch *
handleMoveLogic(touch); handleMoveLogic(touch);
} }
} }
break; break;
case TouchEventType::CANCELED: case TouchEventType::CANCELED:
case TouchEventType::ENDED: case TouchEventType::ENDED:
{ {
@ -666,6 +821,7 @@ void PageView::copySpecialProperties(Widget *widget)
_pageViewEventSelector = pageView->_pageViewEventSelector; _pageViewEventSelector = pageView->_pageViewEventSelector;
_usingCustomScrollThreshold = pageView->_usingCustomScrollThreshold; _usingCustomScrollThreshold = pageView->_usingCustomScrollThreshold;
_customScrollThreshold = pageView->_customScrollThreshold; _customScrollThreshold = pageView->_customScrollThreshold;
_direction = pageView->_direction;
} }
} }

View File

@ -53,7 +53,7 @@ typedef void (Ref::*SEL_PageViewEvent)(Ref*, PageViewEventType);
#define pagevieweventselector(_SELECTOR)(SEL_PageViewEvent)(&_SELECTOR) #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 class CC_GUI_DLL PageView : public Layout
@ -76,7 +76,15 @@ public:
enum class TouchDirection enum class TouchDirection
{ {
LEFT, LEFT,
RIGHT RIGHT,
UP,
DOWN
};
enum class Direction
{
HORIZONTAL,
VERTICAL
}; };
/** /**
@ -141,7 +149,24 @@ public:
* @param index A given index. * @param index A given index.
*/ */
void removePageAtIndex(ssize_t 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. * @brief Remove all pages of the PageView.
@ -247,11 +272,12 @@ protected:
Layout* createPage(); Layout* createPage();
float getPositionXByIndex(ssize_t idx)const; float getPositionXByIndex(ssize_t idx)const;
float getPositionYByIndex(ssize_t idx)const;
ssize_t getPageCount()const; ssize_t getPageCount()const;
void updateBoundaryPages(); void updateBoundaryPages();
virtual bool scrollPages(float touchOffset); virtual bool scrollPages(Vec2 touchOffset);
void movePages(float offset); void movePages(Vec2 offset);
void pageTurningEvent(); void pageTurningEvent();
void updateAllPagesSize(); void updateAllPagesSize();
void updateAllPagesPosition(); void updateAllPagesPosition();
@ -273,12 +299,15 @@ protected:
enum class AutoScrollDirection enum class AutoScrollDirection
{ {
LEFT, LEFT,
RIGHT RIGHT,
UP,
DOWN
}; };
bool _isAutoScrolling; bool _isAutoScrolling;
float _autoScrollDistance; float _autoScrollDistance;
float _autoScrollSpeed; float _autoScrollSpeed;
AutoScrollDirection _autoScrollDirection; AutoScrollDirection _autoScrollDirection;
Direction _direction;
ssize_t _curPageIdx; ssize_t _curPageIdx;
Vector<Layout*> _pages; Vector<Layout*> _pages;

View File

@ -12,6 +12,7 @@ UIPageViewTests::UIPageViewTests()
ADD_TEST_CASE(UIPageViewTouchPropagationTest); ADD_TEST_CASE(UIPageViewTouchPropagationTest);
ADD_TEST_CASE(UIPageViewDynamicAddAndRemoveTest); ADD_TEST_CASE(UIPageViewDynamicAddAndRemoveTest);
ADD_TEST_CASE(UIPageViewJumpToPageTest); ADD_TEST_CASE(UIPageViewJumpToPageTest);
ADD_TEST_CASE(UIPageViewVerticalTest);
} }
// UIPageViewTest // UIPageViewTest
@ -808,3 +809,97 @@ bool UIPageViewJumpToPageTest::init()
} }
return false; 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<Layout*>(_uiLayer->getChildByTag(81));
Layout* background = dynamic_cast<Layout*>(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<PageView*>(pSender);
_displayValueLabel->setString(StringUtils::format("page = %ld", pageView->getCurPageIndex() + 1));
}
break;
default:
break;
}
}

View File

@ -126,4 +126,20 @@ protected:
cocos2d::ui::Text* _displayValueLabel; 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__) */ #endif /* defined(__TestCpp__UIPageViewTest__) */