diff options
Diffstat (limited to 'src/quick/items/qquicklistview.cpp')
-rw-r--r-- | src/quick/items/qquicklistview.cpp | 56 |
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 |