diff options
-rw-r--r-- | examples/declarative/listview/listview.qml | 1 | ||||
-rw-r--r-- | examples/declarative/parallax/ParallaxView.qml | 3 | ||||
-rw-r--r-- | src/declarative/fx/qfxflickable.cpp | 26 | ||||
-rw-r--r-- | src/declarative/fx/qfxlistview.cpp | 80 |
4 files changed, 92 insertions, 18 deletions
diff --git a/examples/declarative/listview/listview.qml b/examples/declarative/listview/listview.qml index b614904..92acce1 100644 --- a/examples/declarative/listview/listview.qml +++ b/examples/declarative/listview/listview.qml @@ -72,5 +72,6 @@ Rectangle { preferredHighlightBegin: 125 preferredHighlightEnd: 125 highlightRangeMode: "StrictlyEnforceRange" + flickDeceleration: 1000 } } diff --git a/examples/declarative/parallax/ParallaxView.qml b/examples/declarative/parallax/ParallaxView.qml index bad9b85..50ab72c 100644 --- a/examples/declarative/parallax/ParallaxView.qml +++ b/examples/declarative/parallax/ParallaxView.qml @@ -25,7 +25,8 @@ Item { anchors.fill: parent model: VisualItemModel { id: visualModel } - highlight: Item { height: 1; width: 1} + highlight: Rectangle { height: 1; width: 1 } + highlightMoveSpeed: 2000 preferredHighlightBegin: 0 preferredHighlightEnd: 0 highlightRangeMode: "StrictlyEnforceRange" diff --git a/src/declarative/fx/qfxflickable.cpp b/src/declarative/fx/qfxflickable.cpp index 92e79dd..659193d 100644 --- a/src/declarative/fx/qfxflickable.cpp +++ b/src/declarative/fx/qfxflickable.cpp @@ -57,6 +57,8 @@ QT_BEGIN_NAMESPACE static const int DragThreshold = 8; static const int FlickThreshold = 20; +// Really slow flicks can be annoying. +static const int minimumFlickVelocity = 200; class QFxFlickableVisibleArea : public QObject { @@ -183,6 +185,8 @@ void QFxFlickablePrivate::flickX(qreal velocity) { Q_Q(QFxFlickable); qreal maxDistance = -1; + if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks. + velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity; // -ve velocity means list is moving up if (velocity > 0) { if (_moveX.value() < q->minXExtent()) @@ -686,8 +690,8 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) if (rejectX) velocityX = 0; if (moved) { - q->viewportMoved(); q->movementStarting(); + q->viewportMoved(); } lastPos = event->pos(); @@ -707,15 +711,23 @@ void QFxFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *even } vTime = timeline.time(); - if (qAbs(velocityY) > 10 && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) - flickY(velocityY); - else + if (qAbs(velocityY) > 10 && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) { + qreal velocity = velocityY; + if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks. + velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity; + flickY(velocity); + } else { fixupY(); + } - if (qAbs(velocityX) > 10 && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) - flickX(velocityX); - else + if (qAbs(velocityX) > 10 && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) { + qreal velocity = velocityX; + if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks. + velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity; + flickX(velocity); + } else { fixupX(); + } stealMouse = false; lastPosTime = QTime(); diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index fbb91b1..e970ddd 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -691,8 +691,7 @@ void QFxListViewPrivate::updateHighlight() { if ((!currentItem && highlight) || (currentItem && !highlight)) createHighlight(); - updateTrackedItem(); - if (currentItem && autoHighlight && highlight && !pressed && moveReason != QFxListViewPrivate::Mouse) { + if (currentItem && autoHighlight && highlight && !moving) { // auto-update highlight highlightPosAnimator->setSourceValue(currentItem->position()); highlightSizeAnimator->setSourceValue(currentItem->size()); @@ -704,6 +703,7 @@ void QFxListViewPrivate::updateHighlight() highlight->item->setHeight(currentItem->item->height()); } } + updateTrackedItem(); } void QFxListViewPrivate::updateSections() @@ -832,8 +832,10 @@ void QFxListViewPrivate::flickX(qreal velocity) { Q_Q(QFxListView); - if (!haveHighlightRange || highlightRange != QFxListView::StrictlyEnforceRange) + if (!haveHighlightRange || highlightRange != QFxListView::StrictlyEnforceRange) { QFxFlickablePrivate::flickX(velocity); + return; + } qreal maxDistance = -1; // -ve velocity means list is moving up @@ -855,19 +857,20 @@ void QFxListViewPrivate::flickX(qreal velocity) v = maxVelocity; } qreal accel = deceleration; - qreal maxAccel = (v * v) / (2.0f * maxDistance); + qreal v2 = v * v; + qreal maxAccel = v2 / (2.0f * maxDistance); if (maxAccel < accel) { // If we are not flicking to the end then attempt to stop exactly on an item boundary - qreal dist = (v * v) / accel / 2.0; + qreal dist = v2 / accel / 2.0; if (v > 0) dist = -dist; - dist = -_moveX.value() - snapPosAt(-_moveX.value() + dist + highlightRangeStart); + dist = -_moveX.value() - snapPosAt(-(_moveX.value() - highlightRangeStart) + dist) + highlightRangeStart; if (v < 0 && dist >= 0 || v > 0 && dist <= 0) { timeline.reset(_moveX); fixupX(); return; } - accel = (v * v) / (2.0f * qAbs(dist)); + accel = v2 / (2.0f * qAbs(dist)); } timeline.reset(_moveX); timeline.accel(_moveX, v, accel, maxDistance); @@ -885,7 +888,60 @@ void QFxListViewPrivate::flickX(qreal velocity) void QFxListViewPrivate::flickY(qreal velocity) { - QFxFlickablePrivate::flickY(velocity); + Q_Q(QFxListView); + + if (!haveHighlightRange || highlightRange != QFxListView::StrictlyEnforceRange) { + QFxFlickablePrivate::flickY(velocity); + return; + } + + qreal maxDistance = -1; + // -ve velocity means list is moving up + if (velocity > 0) { + if (_moveY.value() < q->minYExtent()) + maxDistance = qAbs(q->minYExtent() -_moveY.value() + (overShoot?30:0)); + flickTargetY = q->minYExtent(); + } else { + if (_moveY.value() > q->maxYExtent()) + maxDistance = qAbs(q->maxYExtent() - _moveY.value()) + (overShoot?30:0); + flickTargetY = q->maxYExtent(); + } + if (maxDistance > 0) { + qreal v = velocity; + if (maxVelocity != -1 && maxVelocity < qAbs(v)) { + if (v < 0) + v = -maxVelocity; + else + v = maxVelocity; + } + qreal accel = deceleration; + qreal v2 = v * v; + qreal maxAccel = v2 / (2.0f * maxDistance); + if (maxAccel < accel) { + // If we are not flicking to the end then attempt to stop exactly on an item boundary + qreal dist = v2 / accel / 2.0; + if (v > 0) + dist = -dist; + dist = -_moveY.value() - snapPosAt(-(_moveY.value() - highlightRangeStart) + dist) + highlightRangeStart; + if (v < 0 && dist >= 0 || v > 0 && dist <= 0) { + timeline.reset(_moveY); + fixupY(); + return; + } + accel = v2 / (2.0f * qAbs(dist)); + } + timeline.reset(_moveY); + timeline.accel(_moveY, v, accel, maxDistance); + timeline.execute(fixupYEvent); + if (!flicked) { + flicked = true; + emit q->flickingChanged(); + emit q->flickStarted(); + } + } else { + timeline.reset(_moveY); + fixupY(); + } } //---------------------------------------------------------------------------- @@ -1185,6 +1241,10 @@ void QFxListView::setHighlight(QmlComponent *highlight) \snippet doc/src/snippets/declarative/listview/highlight.qml 1 + Note that the highlight animation also affects the way that the view + is scrolled. This is because the view moves to maintain the + highlight within the preferred highlight range (or visible viewport). + \sa highlight */ bool QFxListView::highlightFollowsCurrentItem() const @@ -1445,7 +1505,7 @@ void QFxListView::viewportMoved() Q_D(QFxListView); QFxFlickable::viewportMoved(); refill(); - if (isFlicking() || d->pressed) + if (isFlicking() || d->moving) d->moveReason = QFxListViewPrivate::Mouse; if (d->moveReason == QFxListViewPrivate::Mouse) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { @@ -1606,7 +1666,7 @@ void QFxListView::trackedPositionChanged() Q_D(QFxListView); if (!d->trackedItem) return; - if (!isFlicking() && !d->pressed && d->moveReason != QFxListViewPrivate::Mouse) { + if (!isFlicking() && !d->moving && d->moveReason != QFxListViewPrivate::Mouse) { const qreal trackedPos = d->trackedItem->position(); if (d->haveHighlightRange) { if (d->highlightRange == StrictlyEnforceRange) { |