void ScrollView::processAutoScrolling(float deltaTime)
{
    // Make auto scroll shorter if it needs to deaccelerate.
    float brakingFactor = (isNecessaryAutoScrollBrake() ? OUT_OF_BOUNDARY_BREAKING_FACTOR : 1);
    
    // Elapsed time
    _autoScrollAccumulatedTime += deltaTime * (1 / brakingFactor);
    
    // Calculate the progress percentage
    float percentage = MIN(1, _autoScrollAccumulatedTime / _autoScrollTotalTime);
    if(_autoScrollAttenuate)
    {
        // Use quintic(5th degree) polynomial
        percentage = tweenfunc::quintEaseOut(percentage);
    }
    
    // Calculate the new position
    Vec2 newPosition = _autoScrollStartPosition + (_autoScrollTargetDelta * percentage);
    bool reachedEnd = std::abs(percentage - 1) <= this->getAutoScrollStopEpsilon();
    
    if (reachedEnd)
    {
        newPosition = _autoScrollStartPosition + _autoScrollTargetDelta;
    }

    if(_bounceEnabled)
    {
        // The new position is adjusted if out of boundary
        newPosition = _autoScrollBrakingStartPosition + (newPosition - _autoScrollBrakingStartPosition) * brakingFactor;
    }
    else
    {
        // Don't let go out of boundary
        Vec2 moveDelta = newPosition - getInnerContainerPosition();
        Vec2 outOfBoundary = getHowMuchOutOfBoundary(moveDelta);
        if (!fltEqualZero(outOfBoundary))
        {
            newPosition += outOfBoundary;
            reachedEnd = true;
        }
    }

    // Finish auto scroll if it ended
    if(reachedEnd)
    {
        _autoScrolling = false;
        dispatchEvent(SCROLLVIEW_EVENT_AUTOSCROLL_ENDED, EventType::AUTOSCROLL_ENDED);
    }

    moveInnerContainer(newPosition - getInnerContainerPosition(), reachedEnd);
}
void ScrollView::moveInnerContainer(const Vec2& deltaMove, bool canStartBounceBack)
{
    Vec2 adjustedMove = flattenVectorByDirection(deltaMove);

    setInnerContainerPosition(getInnerContainerPosition() + adjustedMove);

    Vec2 outOfBoundary = getHowMuchOutOfBoundary();
    updateScrollBar(outOfBoundary);

    if(_bounceEnabled && canStartBounceBack)
    {
        startBounceBackIfNeeded();
    }
}
Beispiel #3
0
void ListView::jumpToItem(ssize_t itemIndex, const Vec2& positionRatioInView, const Vec2& itemAnchorPoint)
{
    Widget* item = getItem(itemIndex);
    if (item == nullptr)
    {
        return;
    }
    doLayout();

    Vec2 destination = calculateItemDestination(positionRatioInView, item, itemAnchorPoint);
    if(!_bounceEnabled)
    {
        Vec2 delta = destination - getInnerContainerPosition();
        Vec2 outOfBoundary = getHowMuchOutOfBoundary(delta);
        destination += outOfBoundary;
    }
    jumpToDestination(destination);
}
bool ScrollView::isNecessaryAutoScrollBrake()
{
    if(_autoScrollBraking)
    {
        return true;
    }

    if(isOutOfBoundary())
    {
        // It just went out of boundary.
        if(!_autoScrollCurrentlyOutOfBoundary)
        {
            _autoScrollCurrentlyOutOfBoundary = true;
            _autoScrollBraking = true;
            _autoScrollBrakingStartPosition = getInnerContainerPosition();
            return true;
        }
    }
    else
    {
        _autoScrollCurrentlyOutOfBoundary = false;
    }
    return false;
}
void ScrollView::jumpToDestination(const Vec2 &des)
{
    _autoScrolling = false;
    moveInnerContainer(des - getInnerContainerPosition(), true);
}
float ScrollView::getScrolledPercentHorizontal() const {
    const float minX = getContentSize().width - getInnerContainerSize().width;
    return getInnerContainerPosition().x / minX * 100.f;
}
float ScrollView::getScrolledPercentVertical() const {
    const float minY = getContentSize().height - getInnerContainerSize().height;
    return (1.f - getInnerContainerPosition().y / minY)*100.f;
}