mirror of https://github.com/axmolengine/axmol.git
Merge pull request #13646 from neokim/refactor_scrollview_inertia_scroll
Refactor scroll view's inertia scroll
This commit is contained in:
commit
75882e64a0
|
@ -31,11 +31,10 @@ THE SOFTWARE.
|
||||||
#include "2d/CCCamera.h"
|
#include "2d/CCCamera.h"
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
namespace ui {
|
static const float OUT_OF_BOUND_TIME_RESCALE = 0.05f;
|
||||||
|
static const float OUT_OF_BOUND_DISTANCE_RESCALE = 0.05f;
|
||||||
static const float INERTIA_DEACCELERATION = 700.0f;
|
|
||||||
static const float INERTIA_VELOCITY_MAX = 2500;
|
|
||||||
static const float BOUNCE_BACK_DURATION = 1.0f;
|
static const float BOUNCE_BACK_DURATION = 1.0f;
|
||||||
|
|
||||||
#define MOVE_INCH 7.0f/160.0f
|
#define MOVE_INCH 7.0f/160.0f
|
||||||
|
|
||||||
static float convertDistanceFromPointToInch(const Vec2& dis)
|
static float convertDistanceFromPointToInch(const Vec2& dis)
|
||||||
|
@ -46,6 +45,8 @@ static float convertDistanceFromPointToInch(const Vec2& dis)
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
IMPLEMENT_CLASS_GUI_INFO(ScrollView)
|
IMPLEMENT_CLASS_GUI_INFO(ScrollView)
|
||||||
|
|
||||||
ScrollView::ScrollView():
|
ScrollView::ScrollView():
|
||||||
|
@ -57,17 +58,17 @@ _leftBoundary(0.0f),
|
||||||
_rightBoundary(0.0f),
|
_rightBoundary(0.0f),
|
||||||
_bePressed(false),
|
_bePressed(false),
|
||||||
_childFocusCancelOffsetInInch(MOVE_INCH),
|
_childFocusCancelOffsetInInch(MOVE_INCH),
|
||||||
_inertiaScrollEnabled(true),
|
_touchMovePreviousTimestamp(0),
|
||||||
_inertiaScrolling(false),
|
|
||||||
_inertiaPrevTouchTimestamp(0),
|
|
||||||
_inertiaScrollExpectedTime(0),
|
|
||||||
_inertiaScrollElapsedTime(0),
|
|
||||||
_autoScrolling(false),
|
_autoScrolling(false),
|
||||||
_autoScrollAttenuate(true),
|
_autoScrollAttenuate(true),
|
||||||
_autoScrollDuration(0),
|
_autoScrollDuration(0),
|
||||||
_autoScrollAccumulatedTime(0),
|
_autoScrollAccumulatedTime(0),
|
||||||
|
_autoScrollCompleteCallback(nullptr),
|
||||||
|
_autoScrollMoveCallback(nullptr),
|
||||||
|
_outOfBoundaryDuringInertiaScroll(false),
|
||||||
|
_inertiaScrollEnabled(true),
|
||||||
|
_inertiaScrolling(false),
|
||||||
_bounceEnabled(false),
|
_bounceEnabled(false),
|
||||||
_bouncingBack(false),
|
|
||||||
_scrollBarEnabled(true),
|
_scrollBarEnabled(true),
|
||||||
_verticalScrollBar(nullptr),
|
_verticalScrollBar(nullptr),
|
||||||
_horizontalScrollBar(nullptr),
|
_horizontalScrollBar(nullptr),
|
||||||
|
@ -223,6 +224,10 @@ const Size& ScrollView::getInnerContainerSize() const
|
||||||
|
|
||||||
void ScrollView::setInnerContainerPosition(const Vec2 &position)
|
void ScrollView::setInnerContainerPosition(const Vec2 &position)
|
||||||
{
|
{
|
||||||
|
if(position == _innerContainer->getPosition())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
_innerContainer->setPosition(position);
|
_innerContainer->setPosition(position);
|
||||||
|
|
||||||
this->retain();
|
this->retain();
|
||||||
|
@ -340,8 +345,27 @@ bool ScrollView::startBounceBackIfNeeded()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_bouncingBack = true;
|
startAutoScroll(outOfBoundary, BOUNCE_BACK_DURATION, true,
|
||||||
startAutoScroll(outOfBoundary, BOUNCE_BACK_DURATION, true);
|
nullptr,
|
||||||
|
[this](const Vec2& moveDelta) {
|
||||||
|
if(moveDelta.x > 0)
|
||||||
|
{
|
||||||
|
processScrollEvent(MoveDirection::RIGHT, true);
|
||||||
|
}
|
||||||
|
else if(moveDelta.x < 0)
|
||||||
|
{
|
||||||
|
processScrollEvent(MoveDirection::LEFT, true);
|
||||||
|
}
|
||||||
|
if(moveDelta.y > 0)
|
||||||
|
{
|
||||||
|
processScrollEvent(MoveDirection::TOP, true);
|
||||||
|
}
|
||||||
|
else if(moveDelta.y < 0)
|
||||||
|
{
|
||||||
|
processScrollEvent(MoveDirection::BOTTOM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,57 +393,16 @@ Vec2 ScrollView::getHowMuchOutOfBoundary(const Vec2& addition) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollView::processAutoScrolling(float deltaTime)
|
|
||||||
{
|
|
||||||
_autoScrollAccumulatedTime += deltaTime;
|
|
||||||
float percentage = _autoScrollAccumulatedTime / _autoScrollDuration;
|
|
||||||
if(percentage >= 1)
|
|
||||||
{
|
|
||||||
moveChildrenToPosition(_autoScrollStartPosition + _autoScrollTargetDelta);
|
|
||||||
_autoScrolling = false;
|
|
||||||
_bouncingBack = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(_autoScrollAttenuate)
|
|
||||||
{
|
|
||||||
percentage = tweenfunc::quintEaseOut(percentage);
|
|
||||||
}
|
|
||||||
Vec2 moveDelta = _autoScrollTargetDelta * percentage;
|
|
||||||
moveChildrenToPosition(_autoScrollStartPosition + moveDelta);
|
|
||||||
|
|
||||||
// Dispatch related events if bouncing
|
|
||||||
if(_bouncingBack)
|
|
||||||
{
|
|
||||||
if(moveDelta.x > 0)
|
|
||||||
{
|
|
||||||
processScrollEvent(MoveDirection::RIGHT, true);
|
|
||||||
}
|
|
||||||
else if(moveDelta.x < 0)
|
|
||||||
{
|
|
||||||
processScrollEvent(MoveDirection::LEFT, true);
|
|
||||||
}
|
|
||||||
if(moveDelta.y > 0)
|
|
||||||
{
|
|
||||||
processScrollEvent(MoveDirection::TOP, true);
|
|
||||||
}
|
|
||||||
else if(moveDelta.y < 0)
|
|
||||||
{
|
|
||||||
processScrollEvent(MoveDirection::BOTTOM, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScrollView::isOutOfBoundary(MoveDirection dir) const
|
bool ScrollView::isOutOfBoundary(MoveDirection dir) const
|
||||||
{
|
{
|
||||||
switch(dir)
|
switch(dir)
|
||||||
{
|
{
|
||||||
case MoveDirection::TOP: return _innerContainer->getTopBoundary() < _topBoundary;
|
case MoveDirection::TOP: return _innerContainer->getTopBoundary() < _topBoundary;
|
||||||
case MoveDirection::BOTTOM: return _innerContainer->getBottomBoundary() > _bottomBoundary;
|
case MoveDirection::BOTTOM: return _innerContainer->getBottomBoundary() > _bottomBoundary;
|
||||||
case MoveDirection::LEFT: return _innerContainer->getLeftBoundary() > _leftBoundary;
|
case MoveDirection::LEFT: return _innerContainer->getLeftBoundary() > _leftBoundary;
|
||||||
case MoveDirection::RIGHT: return _innerContainer->getRightBoundary() < _rightBoundary;
|
case MoveDirection::RIGHT: return _innerContainer->getRightBoundary() < _rightBoundary;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScrollView::isOutOfBoundaryTopOrBottom() const
|
bool ScrollView::isOutOfBoundaryTopOrBottom() const
|
||||||
|
@ -432,7 +415,17 @@ bool ScrollView::isOutOfBoundaryLeftOrRight() const
|
||||||
return isOutOfBoundary(MoveDirection::LEFT) || isOutOfBoundary(MoveDirection::RIGHT);
|
return isOutOfBoundary(MoveDirection::LEFT) || isOutOfBoundary(MoveDirection::RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollView::startAutoScroll(const Vec2& deltaMove, float duration, bool attenuated)
|
bool ScrollView::isOutOfBoundary() const
|
||||||
|
{
|
||||||
|
return isOutOfBoundaryTopOrBottom() || isOutOfBoundaryLeftOrRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollView::startAutoScrollChildrenWithDestination(const Vec2& des, float second, bool attenuated)
|
||||||
|
{
|
||||||
|
startAutoScroll(des - _innerContainer->getPosition(), second, attenuated);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollView::startAutoScroll(const Vec2& deltaMove, float duration, bool attenuated, std::function<void()> completeCallback, std::function<void(const Vec2&)> moveCallback)
|
||||||
{
|
{
|
||||||
_autoScrolling = true;
|
_autoScrolling = true;
|
||||||
_autoScrollTargetDelta = deltaMove;
|
_autoScrollTargetDelta = deltaMove;
|
||||||
|
@ -440,11 +433,79 @@ void ScrollView::startAutoScroll(const Vec2& deltaMove, float duration, bool att
|
||||||
_autoScrollStartPosition = _innerContainer->getPosition();
|
_autoScrollStartPosition = _innerContainer->getPosition();
|
||||||
_autoScrollDuration = duration;
|
_autoScrollDuration = duration;
|
||||||
_autoScrollAccumulatedTime = 0;
|
_autoScrollAccumulatedTime = 0;
|
||||||
|
_autoScrollCompleteCallback = completeCallback;
|
||||||
|
_autoScrollMoveCallback = moveCallback;
|
||||||
|
_outOfBoundaryDuringInertiaScroll = false;
|
||||||
|
_outOfBoundaryPositionDuringInertiaScroll = Vec2::ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollView::startAutoScrollChildrenWithDestination(const Vec2& des, float second, bool attenuated)
|
void ScrollView::processAutoScrolling(float deltaTime)
|
||||||
{
|
{
|
||||||
startAutoScroll(des - _innerContainer->getPosition(), second, attenuated);
|
// Shorten the auto scroll distance and time if it is out of boundary during inertia scroll.
|
||||||
|
float timeRescale = 1;
|
||||||
|
float distanceRescale = 1;
|
||||||
|
{
|
||||||
|
bool currentlyOutOfBoundDuringInertiaScroll = (_inertiaScrolling && isOutOfBoundary());
|
||||||
|
if(!_outOfBoundaryDuringInertiaScroll && currentlyOutOfBoundDuringInertiaScroll)
|
||||||
|
{
|
||||||
|
_outOfBoundaryDuringInertiaScroll = true;
|
||||||
|
_outOfBoundaryPositionDuringInertiaScroll = getInnerContainerPosition();
|
||||||
|
}
|
||||||
|
timeRescale = (_outOfBoundaryDuringInertiaScroll ? OUT_OF_BOUND_TIME_RESCALE : 1);
|
||||||
|
distanceRescale = (_outOfBoundaryDuringInertiaScroll ? OUT_OF_BOUND_DISTANCE_RESCALE : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the percentage
|
||||||
|
float percentage = 0;
|
||||||
|
{
|
||||||
|
_autoScrollAccumulatedTime += deltaTime * (1 / timeRescale);
|
||||||
|
percentage = MIN(1, _autoScrollAccumulatedTime / _autoScrollDuration);
|
||||||
|
if(_autoScrollAttenuate)
|
||||||
|
{
|
||||||
|
// Use quintic(5th degree) polynomial
|
||||||
|
percentage = tweenfunc::quintEaseOut(percentage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the new position
|
||||||
|
Vec2 deltaFromInitialPosition = _autoScrollTargetDelta * percentage;
|
||||||
|
Vec2 newPosition = _autoScrollStartPosition + deltaFromInitialPosition;
|
||||||
|
bool reachedEnd = false;
|
||||||
|
|
||||||
|
// Adjust the new position according to the bounce opiton
|
||||||
|
{
|
||||||
|
if(_bounceEnabled)
|
||||||
|
{
|
||||||
|
newPosition = _outOfBoundaryPositionDuringInertiaScroll + (newPosition - _outOfBoundaryPositionDuringInertiaScroll) * distanceRescale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vec2 moveDelta = newPosition - getInnerContainerPosition();
|
||||||
|
Vec2 outOfBoundary = getHowMuchOutOfBoundary(moveDelta);
|
||||||
|
if(outOfBoundary != Vec2::ZERO)
|
||||||
|
{
|
||||||
|
newPosition += outOfBoundary;
|
||||||
|
reachedEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
moveChildrenToPosition(newPosition);
|
||||||
|
|
||||||
|
if(_autoScrollMoveCallback)
|
||||||
|
{
|
||||||
|
_autoScrollMoveCallback(getInnerContainerPosition() - newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish auto scroll if it ended
|
||||||
|
if(percentage == 1 || reachedEnd)
|
||||||
|
{
|
||||||
|
_autoScrolling = false;
|
||||||
|
if(_autoScrollCompleteCallback)
|
||||||
|
{
|
||||||
|
_autoScrollCompleteCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollView::jumpToDestination(const Vec2 &des)
|
void ScrollView::jumpToDestination(const Vec2 &des)
|
||||||
|
@ -462,75 +523,43 @@ void ScrollView::jumpToDestination(const Vec2 &des)
|
||||||
moveChildrenToPosition(Vec2(finalOffsetX, finalOffsetY));
|
moveChildrenToPosition(Vec2(finalOffsetX, finalOffsetY));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollView::startInertiaScroll()
|
Vec2 ScrollView::calculateTouchMoveVelocity() const
|
||||||
{
|
{
|
||||||
float totalDuration = 0;
|
float totalDuration = 0;
|
||||||
for(auto &timeDelta : _inertiaTouchTimeDeltas)
|
for(auto &timeDelta : _touchMoveTimeDeltas)
|
||||||
{
|
{
|
||||||
totalDuration += timeDelta;
|
totalDuration += timeDelta;
|
||||||
}
|
}
|
||||||
if(totalDuration == 0 || totalDuration >= 0.5f)
|
if(totalDuration == 0 || totalDuration >= 0.5f)
|
||||||
{
|
{
|
||||||
return;
|
return Vec2::ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
_inertiaScrolling = true;
|
|
||||||
|
|
||||||
// Calcualte the initial velocity
|
|
||||||
Vec2 totalMovement;
|
Vec2 totalMovement;
|
||||||
for(auto &displacement : _inertiaTouchDisplacements)
|
for(auto &displacement : _touchMoveDisplacements)
|
||||||
{
|
|
||||||
totalMovement += displacement;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto i = _inertiaTouchDisplacements.begin(); i != _inertiaTouchDisplacements.end(); ++i)
|
|
||||||
{
|
{
|
||||||
totalMovement += (*i);
|
totalMovement += displacement;
|
||||||
}
|
}
|
||||||
totalMovement.x = (_direction == Direction::VERTICAL ? 0 : totalMovement.x);
|
return totalMovement / totalDuration;
|
||||||
totalMovement.y = (_direction == Direction::HORIZONTAL ? 0 : totalMovement.y);
|
|
||||||
|
|
||||||
_inertiaInitiVelocity = totalMovement / totalDuration;
|
|
||||||
_inertiaInitiVelocity.x = MIN(_inertiaInitiVelocity.x, INERTIA_VELOCITY_MAX);
|
|
||||||
_inertiaInitiVelocity.y = MIN(_inertiaInitiVelocity.y, INERTIA_VELOCITY_MAX);
|
|
||||||
_inertiaInitiVelocity.x = MAX(_inertiaInitiVelocity.x, -INERTIA_VELOCITY_MAX);
|
|
||||||
_inertiaInitiVelocity.y = MAX(_inertiaInitiVelocity.y, -INERTIA_VELOCITY_MAX);
|
|
||||||
|
|
||||||
// Calculate values for ease out
|
|
||||||
_inertiaScrollExpectedTime = _inertiaInitiVelocity.length() / INERTIA_DEACCELERATION;
|
|
||||||
_inertiaScrollElapsedTime = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollView::processInertiaScrolling(float dt)
|
void ScrollView::startInertiaScroll(const Vec2& touchMoveVelocity)
|
||||||
{
|
{
|
||||||
_inertiaScrollElapsedTime += dt;
|
Vec2 initialVelocity = touchMoveVelocity;
|
||||||
if(isOutOfBoundaryLeftOrRight() || isOutOfBoundaryTopOrBottom())
|
initialVelocity.x = (_direction == Direction::VERTICAL ? 0 : initialVelocity.x);
|
||||||
{
|
initialVelocity.y = (_direction == Direction::HORIZONTAL ? 0 : initialVelocity.y);
|
||||||
// If the inner container is out of boundary, shorten the inertia time.
|
|
||||||
_inertiaScrollElapsedTime += dt * (45000 / INERTIA_DEACCELERATION);
|
const float MOVEMENT_FACTOR = 0.7f;
|
||||||
}
|
Vec2 inertiaTotalDisplacement = initialVelocity * MOVEMENT_FACTOR;
|
||||||
float percentage = _inertiaScrollElapsedTime / _inertiaScrollExpectedTime;
|
|
||||||
if(percentage >= 1)
|
// Calculate the duration from the initial velocity according to quintic polynomial.
|
||||||
{
|
float duration = sqrtf(sqrtf(initialVelocity.length() / 5));
|
||||||
|
|
||||||
|
_inertiaScrolling = true;
|
||||||
|
startAutoScroll(inertiaTotalDisplacement, duration, true, [this]() {
|
||||||
_inertiaScrolling = false;
|
_inertiaScrolling = false;
|
||||||
startBounceBackIfNeeded();
|
startBounceBackIfNeeded();
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
percentage = tweenfunc::quartEaseOut(percentage);
|
|
||||||
|
|
||||||
Vec2 inertiaVelocity = _inertiaInitiVelocity * (1 - percentage);
|
|
||||||
Vec2 displacement = inertiaVelocity * dt;
|
|
||||||
if(!_bounceEnabled)
|
|
||||||
{
|
|
||||||
Vec2 outOfBoundary = getHowMuchOutOfBoundary(displacement);
|
|
||||||
if(outOfBoundary != Vec2::ZERO)
|
|
||||||
{
|
|
||||||
// Don't allow to go out of boundary
|
|
||||||
displacement += outOfBoundary;
|
|
||||||
_inertiaScrolling = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
moveChildren(displacement.x, displacement.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScrollView::scrollChildren(float touchOffsetX, float touchOffsetY)
|
bool ScrollView::scrollChildren(float touchOffsetX, float touchOffsetY)
|
||||||
|
@ -803,36 +832,18 @@ void ScrollView::jumpToPercentBothDirection(const Vec2& percent)
|
||||||
jumpToDestination(Vec2(-(percent.x * w / 100.0f), minY + percent.y * h / 100.0f));
|
jumpToDestination(Vec2(-(percent.x * w / 100.0f), minY + percent.y * h / 100.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollView::startRecordSlidAction()
|
|
||||||
{
|
|
||||||
if (_inertiaScrolling)
|
|
||||||
{
|
|
||||||
_inertiaScrolling = false;
|
|
||||||
}
|
|
||||||
if(_autoScrolling)
|
|
||||||
{
|
|
||||||
_autoScrolling = false;
|
|
||||||
_bouncingBack = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollView::endRecordSlidAction()
|
|
||||||
{
|
|
||||||
bool bounceBackStarted = startBounceBackIfNeeded();
|
|
||||||
if(!bounceBackStarted && _inertiaScrollEnabled)
|
|
||||||
{
|
|
||||||
startInertiaScroll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollView::handlePressLogic(Touch *touch)
|
void ScrollView::handlePressLogic(Touch *touch)
|
||||||
{
|
{
|
||||||
startRecordSlidAction();
|
|
||||||
_bePressed = true;
|
_bePressed = true;
|
||||||
|
_autoScrolling = false;
|
||||||
|
_inertiaScrolling = false;
|
||||||
|
|
||||||
_inertiaPrevTouchTimestamp = utils::getTimeInMilliseconds();
|
// Initialize touch move information
|
||||||
_inertiaTouchDisplacements.clear();
|
{
|
||||||
_inertiaTouchTimeDeltas.clear();
|
_touchMovePreviousTimestamp = utils::getTimeInMilliseconds();
|
||||||
|
_touchMoveDisplacements.clear();
|
||||||
|
_touchMoveTimeDeltas.clear();
|
||||||
|
}
|
||||||
|
|
||||||
if(_verticalScrollBar != nullptr)
|
if(_verticalScrollBar != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -857,23 +868,35 @@ void ScrollView::handleMoveLogic(Touch *touch)
|
||||||
Vec2 delta(delta3.x, delta3.y);
|
Vec2 delta(delta3.x, delta3.y);
|
||||||
scrollChildren(delta.x, delta.y);
|
scrollChildren(delta.x, delta.y);
|
||||||
|
|
||||||
while(_inertiaTouchDisplacements.size() > 5)
|
// Gather touch move information for speed calculation
|
||||||
{
|
{
|
||||||
_inertiaTouchDisplacements.pop_front();
|
while(_touchMoveDisplacements.size() > 5)
|
||||||
_inertiaTouchTimeDeltas.pop_front();
|
{
|
||||||
}
|
_touchMoveDisplacements.pop_front();
|
||||||
_inertiaTouchDisplacements.push_back(delta);
|
_touchMoveTimeDeltas.pop_front();
|
||||||
|
}
|
||||||
|
_touchMoveDisplacements.push_back(delta);
|
||||||
|
|
||||||
long long timestamp = utils::getTimeInMilliseconds();
|
long long timestamp = utils::getTimeInMilliseconds();
|
||||||
_inertiaTouchTimeDeltas.push_back((timestamp - _inertiaPrevTouchTimestamp) / 1000.0f);
|
_touchMoveTimeDeltas.push_back((timestamp - _touchMovePreviousTimestamp) / 1000.0f);
|
||||||
_inertiaPrevTouchTimestamp = timestamp;
|
_touchMovePreviousTimestamp = timestamp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollView::handleReleaseLogic(Touch *touch)
|
void ScrollView::handleReleaseLogic(Touch *touch)
|
||||||
{
|
{
|
||||||
endRecordSlidAction();
|
|
||||||
_bePressed = false;
|
_bePressed = false;
|
||||||
|
|
||||||
|
bool bounceBackStarted = startBounceBackIfNeeded();
|
||||||
|
if(!bounceBackStarted && _inertiaScrollEnabled)
|
||||||
|
{
|
||||||
|
Vec2 touchMoveVelocity = calculateTouchMoveVelocity();
|
||||||
|
if(touchMoveVelocity != Vec2::ZERO)
|
||||||
|
{
|
||||||
|
startInertiaScroll(touchMoveVelocity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(_verticalScrollBar != nullptr)
|
if(_verticalScrollBar != nullptr)
|
||||||
{
|
{
|
||||||
_verticalScrollBar->onTouchEnded();
|
_verticalScrollBar->onTouchEnded();
|
||||||
|
@ -928,11 +951,7 @@ void ScrollView::onTouchCancelled(Touch *touch, Event *unusedEvent)
|
||||||
|
|
||||||
void ScrollView::update(float dt)
|
void ScrollView::update(float dt)
|
||||||
{
|
{
|
||||||
if (_inertiaScrolling)
|
if (_autoScrolling)
|
||||||
{
|
|
||||||
processInertiaScrolling(dt);
|
|
||||||
}
|
|
||||||
else if (_autoScrolling)
|
|
||||||
{
|
{
|
||||||
processAutoScrolling(dt);
|
processAutoScrolling(dt);
|
||||||
}
|
}
|
||||||
|
@ -1002,29 +1021,29 @@ void ScrollView::processScrollEvent(MoveDirection dir, bool bounce)
|
||||||
ScrollviewEventType scrollEventType;
|
ScrollviewEventType scrollEventType;
|
||||||
EventType eventType;
|
EventType eventType;
|
||||||
switch(dir) {
|
switch(dir) {
|
||||||
case MoveDirection::TOP:
|
case MoveDirection::TOP:
|
||||||
{
|
{
|
||||||
scrollEventType = (bounce ? SCROLLVIEW_EVENT_BOUNCE_TOP : SCROLLVIEW_EVENT_SCROLL_TO_TOP);
|
scrollEventType = (bounce ? SCROLLVIEW_EVENT_BOUNCE_TOP : SCROLLVIEW_EVENT_SCROLL_TO_TOP);
|
||||||
eventType = (bounce ? EventType::BOUNCE_TOP : EventType::SCROLL_TO_TOP);
|
eventType = (bounce ? EventType::BOUNCE_TOP : EventType::SCROLL_TO_TOP);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MoveDirection::BOTTOM:
|
case MoveDirection::BOTTOM:
|
||||||
{
|
{
|
||||||
scrollEventType = (bounce ? SCROLLVIEW_EVENT_BOUNCE_BOTTOM : SCROLLVIEW_EVENT_SCROLL_TO_BOTTOM);
|
scrollEventType = (bounce ? SCROLLVIEW_EVENT_BOUNCE_BOTTOM : SCROLLVIEW_EVENT_SCROLL_TO_BOTTOM);
|
||||||
eventType = (bounce ? EventType::BOUNCE_BOTTOM : EventType::SCROLL_TO_BOTTOM);
|
eventType = (bounce ? EventType::BOUNCE_BOTTOM : EventType::SCROLL_TO_BOTTOM);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MoveDirection::LEFT:
|
case MoveDirection::LEFT:
|
||||||
{
|
{
|
||||||
scrollEventType = (bounce ? SCROLLVIEW_EVENT_BOUNCE_LEFT : SCROLLVIEW_EVENT_SCROLL_TO_LEFT);
|
scrollEventType = (bounce ? SCROLLVIEW_EVENT_BOUNCE_LEFT : SCROLLVIEW_EVENT_SCROLL_TO_LEFT);
|
||||||
eventType = (bounce ? EventType::BOUNCE_LEFT : EventType::SCROLL_TO_LEFT);
|
eventType = (bounce ? EventType::BOUNCE_LEFT : EventType::SCROLL_TO_LEFT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MoveDirection::RIGHT:
|
case MoveDirection::RIGHT:
|
||||||
{
|
{
|
||||||
scrollEventType = (bounce ? SCROLLVIEW_EVENT_BOUNCE_RIGHT : SCROLLVIEW_EVENT_SCROLL_TO_RIGHT);
|
scrollEventType = (bounce ? SCROLLVIEW_EVENT_BOUNCE_RIGHT : SCROLLVIEW_EVENT_SCROLL_TO_RIGHT);
|
||||||
eventType = (bounce ? EventType::BOUNCE_RIGHT : EventType::SCROLL_TO_RIGHT);
|
eventType = (bounce ? EventType::BOUNCE_RIGHT : EventType::SCROLL_TO_RIGHT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatchEvent(scrollEventType, eventType);
|
dispatchEvent(scrollEventType, eventType);
|
||||||
|
@ -1351,22 +1370,22 @@ void ScrollView::copySpecialProperties(Widget *widget)
|
||||||
_rightBoundary = scrollView->_rightBoundary;
|
_rightBoundary = scrollView->_rightBoundary;
|
||||||
_bePressed = scrollView->_bePressed;
|
_bePressed = scrollView->_bePressed;
|
||||||
_childFocusCancelOffsetInInch = scrollView->_childFocusCancelOffsetInInch;
|
_childFocusCancelOffsetInInch = scrollView->_childFocusCancelOffsetInInch;
|
||||||
setInertiaScrollEnabled(scrollView->_inertiaScrollEnabled);
|
_touchMoveDisplacements = scrollView->_touchMoveDisplacements;
|
||||||
_inertiaScrolling = scrollView->_inertiaScrolling;
|
_touchMoveTimeDeltas = scrollView->_touchMoveTimeDeltas;
|
||||||
_inertiaInitiVelocity = scrollView->_inertiaInitiVelocity;
|
_touchMovePreviousTimestamp = scrollView->_touchMovePreviousTimestamp;
|
||||||
_inertiaTouchDisplacements = scrollView->_inertiaTouchDisplacements;
|
|
||||||
_inertiaTouchTimeDeltas = scrollView->_inertiaTouchTimeDeltas;
|
|
||||||
_inertiaPrevTouchTimestamp = scrollView->_inertiaPrevTouchTimestamp;
|
|
||||||
_inertiaScrollExpectedTime = scrollView->_inertiaScrollExpectedTime;
|
|
||||||
_inertiaScrollElapsedTime = scrollView->_inertiaScrollElapsedTime;
|
|
||||||
_autoScrolling = scrollView->_autoScrolling;
|
_autoScrolling = scrollView->_autoScrolling;
|
||||||
_autoScrollAttenuate = scrollView->_autoScrollAttenuate;
|
_autoScrollAttenuate = scrollView->_autoScrollAttenuate;
|
||||||
_autoScrollStartPosition = scrollView->_autoScrollStartPosition;
|
_autoScrollStartPosition = scrollView->_autoScrollStartPosition;
|
||||||
_autoScrollTargetDelta = scrollView->_autoScrollTargetDelta;
|
_autoScrollTargetDelta = scrollView->_autoScrollTargetDelta;
|
||||||
_autoScrollDuration = scrollView->_autoScrollDuration;
|
_autoScrollDuration = scrollView->_autoScrollDuration;
|
||||||
_autoScrollAccumulatedTime = scrollView->_autoScrollAccumulatedTime;
|
_autoScrollAccumulatedTime = scrollView->_autoScrollAccumulatedTime;
|
||||||
|
_outOfBoundaryDuringInertiaScroll = scrollView->_outOfBoundaryDuringInertiaScroll;
|
||||||
|
_outOfBoundaryPositionDuringInertiaScroll = scrollView->_outOfBoundaryPositionDuringInertiaScroll;
|
||||||
|
_autoScrollCompleteCallback = scrollView->_autoScrollCompleteCallback;
|
||||||
|
_autoScrollMoveCallback = scrollView->_autoScrollMoveCallback;
|
||||||
|
setInertiaScrollEnabled(scrollView->_inertiaScrollEnabled);
|
||||||
|
_inertiaScrolling = scrollView->_inertiaScrolling;
|
||||||
setBounceEnabled(scrollView->_bounceEnabled);
|
setBounceEnabled(scrollView->_bounceEnabled);
|
||||||
_bouncingBack = scrollView->_bouncingBack;
|
|
||||||
_scrollViewEventListener = scrollView->_scrollViewEventListener;
|
_scrollViewEventListener = scrollView->_scrollViewEventListener;
|
||||||
_scrollViewEventSelector = scrollView->_scrollViewEventSelector;
|
_scrollViewEventSelector = scrollView->_scrollViewEventSelector;
|
||||||
_eventCallback = scrollView->_eventCallback;
|
_eventCallback = scrollView->_eventCallback;
|
||||||
|
|
|
@ -568,14 +568,16 @@ protected:
|
||||||
bool isOutOfBoundary(MoveDirection dir) const;
|
bool isOutOfBoundary(MoveDirection dir) const;
|
||||||
bool isOutOfBoundaryTopOrBottom() const;
|
bool isOutOfBoundaryTopOrBottom() const;
|
||||||
bool isOutOfBoundaryLeftOrRight() const;
|
bool isOutOfBoundaryLeftOrRight() const;
|
||||||
|
bool isOutOfBoundary() const;
|
||||||
|
|
||||||
void moveChildren(float offsetX, float offsetY);
|
void moveChildren(float offsetX, float offsetY);
|
||||||
void moveChildrenToPosition(const Vec2& position);
|
void moveChildrenToPosition(const Vec2& position);
|
||||||
|
|
||||||
void startInertiaScroll();
|
Vec2 calculateTouchMoveVelocity() const;
|
||||||
void processInertiaScrolling(float dt);
|
|
||||||
|
|
||||||
void startAutoScroll(const Vec2& deltaMove, float duration, bool attenuated);
|
void startInertiaScroll(const Vec2& touchMoveVelocity);
|
||||||
|
|
||||||
|
void startAutoScroll(const Vec2& deltaMove, float duration, bool attenuated, std::function<void()> completeCallback = nullptr, std::function<void(const Vec2&)> moveCallback = nullptr);
|
||||||
void startAutoScrollChildrenWithDestination(const Vec2& des, float second, bool attenuated);
|
void startAutoScrollChildrenWithDestination(const Vec2& des, float second, bool attenuated);
|
||||||
void processAutoScrolling(float deltaTime);
|
void processAutoScrolling(float deltaTime);
|
||||||
|
|
||||||
|
@ -585,10 +587,6 @@ protected:
|
||||||
|
|
||||||
virtual bool scrollChildren(float touchOffsetX, float touchOffsetY);
|
virtual bool scrollChildren(float touchOffsetX, float touchOffsetY);
|
||||||
|
|
||||||
void startRecordSlidAction();
|
|
||||||
virtual void endRecordSlidAction();
|
|
||||||
|
|
||||||
//ScrollViewProtocol
|
|
||||||
virtual void handlePressLogic(Touch *touch);
|
virtual void handlePressLogic(Touch *touch);
|
||||||
virtual void handleMoveLogic(Touch *touch);
|
virtual void handleMoveLogic(Touch *touch);
|
||||||
virtual void handleReleaseLogic(Touch *touch);
|
virtual void handleReleaseLogic(Touch *touch);
|
||||||
|
@ -617,14 +615,10 @@ protected:
|
||||||
|
|
||||||
float _childFocusCancelOffsetInInch;
|
float _childFocusCancelOffsetInInch;
|
||||||
|
|
||||||
bool _inertiaScrollEnabled;
|
// Touch move speed
|
||||||
bool _inertiaScrolling;
|
std::list<Vec2> _touchMoveDisplacements;
|
||||||
Vec2 _inertiaInitiVelocity;
|
std::list<float> _touchMoveTimeDeltas;
|
||||||
std::list<Vec2> _inertiaTouchDisplacements;
|
long long _touchMovePreviousTimestamp;
|
||||||
std::list<float> _inertiaTouchTimeDeltas;
|
|
||||||
long long _inertiaPrevTouchTimestamp;
|
|
||||||
float _inertiaScrollExpectedTime;
|
|
||||||
float _inertiaScrollElapsedTime;
|
|
||||||
|
|
||||||
bool _autoScrolling;
|
bool _autoScrolling;
|
||||||
bool _autoScrollAttenuate;
|
bool _autoScrollAttenuate;
|
||||||
|
@ -632,9 +626,16 @@ protected:
|
||||||
Vec2 _autoScrollTargetDelta;
|
Vec2 _autoScrollTargetDelta;
|
||||||
float _autoScrollDuration;
|
float _autoScrollDuration;
|
||||||
float _autoScrollAccumulatedTime;
|
float _autoScrollAccumulatedTime;
|
||||||
|
bool _outOfBoundaryDuringInertiaScroll;
|
||||||
|
Vec2 _outOfBoundaryPositionDuringInertiaScroll;
|
||||||
|
std::function<void()> _autoScrollCompleteCallback;
|
||||||
|
std::function<void(const Vec2& moveDelta)> _autoScrollMoveCallback;
|
||||||
|
|
||||||
|
// Inertia scroll
|
||||||
|
bool _inertiaScrollEnabled;
|
||||||
|
bool _inertiaScrolling;
|
||||||
|
|
||||||
bool _bounceEnabled;
|
bool _bounceEnabled;
|
||||||
bool _bouncingBack;
|
|
||||||
|
|
||||||
bool _scrollBarEnabled;
|
bool _scrollBarEnabled;
|
||||||
ScrollViewBar* _verticalScrollBar;
|
ScrollViewBar* _verticalScrollBar;
|
||||||
|
|
Loading…
Reference in New Issue