aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquicklistview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquicklistview.cpp')
-rw-r--r--src/quick/items/qquicklistview.cpp56
1 files changed, 38 insertions, 18 deletions
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 19033e03f1..908801ce1c 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -515,8 +515,8 @@ QString QQuickListViewPrivate::sectionAt(int modelIndex)
qreal QQuickListViewPrivate::snapPosAt(qreal pos)
{
- if (FxViewItem *snapItem = snapItemAt(pos))
- return snapItem->position();
+ if (FxListItemSG *snapItem = static_cast<FxListItemSG*>(snapItemAt(pos)))
+ return snapItem->itemPosition();
if (visibleItems.count()) {
qreal firstPos = (*visibleItems.constBegin())->position();
qreal endPos = (*(--visibleItems.constEnd()))->position();
@@ -530,22 +530,35 @@ qreal QQuickListViewPrivate::snapPosAt(qreal pos)
FxViewItem *QQuickListViewPrivate::snapItemAt(qreal pos)
{
+ const qreal velocity = orient == QQuickListView::Vertical ? vData.velocity : hData.velocity;
FxViewItem *snapItem = nullptr;
+ FxViewItem *prevItem = nullptr;
qreal prevItemSize = 0;
for (FxViewItem *item : qAsConst(visibleItems)) {
if (item->index == -1)
continue;
- qreal itemTop = item->position();
- if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size())
+
+ const FxListItemSG *listItem = static_cast<FxListItemSG *>(item);
+ qreal itemTop = listItem->position();
+ qreal itemSize = listItem->size();
+ if (highlight && itemTop >= pos && listItem->endPosition() <= pos + highlight->size())
return item;
+ if (listItem->section() && velocity > 0) {
+ if (itemTop + listItem->sectionSize() / 2 >= pos && itemTop - prevItemSize / 2 < pos)
+ snapItem = prevItem;
+ itemTop = listItem->itemPosition();
+ itemSize = listItem->itemSize();
+ }
+
// Middle of item and spacing (i.e. the middle of the distance between this item and the next
- qreal halfwayToNextItem = itemTop + (item->size()+spacing) / 2;
+ qreal halfwayToNextItem = itemTop + (itemSize+spacing) / 2;
qreal halfwayToPrevItem = itemTop - (prevItemSize+spacing) / 2;
if (halfwayToNextItem >= pos && halfwayToPrevItem < pos)
snapItem = item;
- prevItemSize = item->size();
+ prevItemSize = listItem->itemSize();
+ prevItem = item;
}
return snapItem;
}
@@ -1501,7 +1514,7 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
qreal tempPosition = isContentFlowReversed() ? -position()-size() : position();
if (snapMode == QQuickListView::SnapOneItem && moveReason == Mouse) {
// if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal dist = data.move.value() - data.pressPos;
qreal bias = 0;
if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < averageSize/2)
bias = averageSize/2;
@@ -1512,13 +1525,13 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
tempPosition -= bias;
}
FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
- if (strictHighlightRange && currentItem && (!topItem || topItem->index != currentIndex)) {
+ if (strictHighlightRange && currentItem && (!topItem || (topItem->index != currentIndex && fixupMode == Immediate))) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
topItem = currentItem;
}
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
- if (strictHighlightRange && currentItem && (!bottomItem || bottomItem->index != currentIndex)) {
+ if (strictHighlightRange && currentItem && (!bottomItem || (bottomItem->index != currentIndex && fixupMode == Immediate))) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
bottomItem = currentItem;
@@ -1530,15 +1543,15 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
pos = isContentFlowReversed() ? - header->position() + highlightRangeStart - size() : header->position() - highlightRangeStart;
} else {
if (isContentFlowReversed())
- pos = qMax(qMin(-topItem->position() + highlightRangeStart - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(topItem->position() - highlightRangeStart, -maxExtent), -minExtent);
+ pos = qMax(qMin(static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart, -maxExtent), -minExtent);
}
} else if (bottomItem && isInBounds) {
if (isContentFlowReversed())
- pos = qMax(qMin(-bottomItem->position() + highlightRangeEnd - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-static_cast<FxListItemSG*>(bottomItem)->itemPosition() + highlightRangeEnd - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(bottomItem->position() - highlightRangeEnd, -maxExtent), -minExtent);
+ pos = qMax(qMin(static_cast<FxListItemSG*>(bottomItem)->itemPosition() - highlightRangeEnd, -maxExtent), -minExtent);
} else {
QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
return;
@@ -1568,7 +1581,10 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
timeline.reset(data.move);
if (viewPos != position()) {
if (fixupMode != Immediate) {
- timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ if (fixupMode == ExtentChanged && data.fixingUp)
+ timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::OutQuad), fixupDuration/2);
+ else
+ timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
data.fixingUp = true;
} else {
timeline.set(data.move, -viewPos);
@@ -1599,7 +1615,7 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
if (data.move.value() < minExtent) {
if (snapMode == QQuickListView::SnapOneItem && !hData.flicking && !vData.flicking) {
// if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal dist = data.move.value() - data.pressPos;
qreal bias = dist < averageSize/2 ? averageSize/2 : 0;
if (isContentFlowReversed())
bias = -bias;
@@ -1616,7 +1632,7 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
if (data.move.value() > maxExtent) {
if (snapMode == QQuickListView::SnapOneItem && !hData.flicking && !vData.flicking) {
// if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal dist = data.move.value() - data.pressPos;
qreal bias = -dist < averageSize/2 ? averageSize/2 : 0;
if (isContentFlowReversed())
bias = -bias;
@@ -1982,7 +1998,7 @@ QQuickListView::~QQuickListView()
The model provides the set of data that is used to create the items
in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
- or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
+ or \l ObjectModel, or provided by C++ model classes. If a C++ model class is
used, it must be a subclass of \l QAbstractItemModel or a simple list.
\sa {qml-data-models}{Data Models}
@@ -2521,7 +2537,11 @@ void QQuickListView::setHighlightResizeDuration(int duration)
the view.
\li ListView.SnapOneItem - the view settles no more than one item away from the first
visible item at the time the mouse button is released. This mode is particularly
- useful for moving one page at a time.
+ useful for moving one page at a time. When SnapOneItem is enabled, the ListView will
+ show a stronger affinity to neighboring items when movement occurs. For example, a
+ short drag that snaps back to the current item with SnapToItem might snap to a
+ neighboring item with SnapOneItem.
+
\endlist
\c snapMode does not affect the \l currentIndex. To update the