fix: notif list viewport jumping around on delegate creation
This commit is contained in:
parent
82f177fa3f
commit
8fbf85da86
3 changed files with 42 additions and 0 deletions
|
|
@ -22,6 +22,7 @@ LazyListView {
|
|||
cacheBuffer: 400
|
||||
asynchronous: true
|
||||
|
||||
onViewportAdjustNeeded: d => container.contentY += d
|
||||
useCustomViewport: true
|
||||
viewport: Qt.rect(0, container.contentY, width, container.height)
|
||||
|
||||
|
|
@ -66,6 +67,7 @@ LazyListView {
|
|||
clearTimer.start();
|
||||
}
|
||||
|
||||
LazyListView.trackViewport: notifInner.expanded || notifInner.nonAnimHeight < notifInner.implicitHeight
|
||||
LazyListView.preferredHeight: closed ? 0 : notifInner.nonAnimHeight
|
||||
LazyListView.visibleHeight: notifInner.implicitHeight
|
||||
implicitHeight: notifInner.implicitHeight
|
||||
|
|
|
|||
|
|
@ -62,6 +62,17 @@ void LazyListViewAttached::setRemoving(bool removing) {
|
|||
emit removingChanged();
|
||||
}
|
||||
|
||||
bool LazyListViewAttached::trackViewport() const {
|
||||
return m_trackViewport;
|
||||
}
|
||||
|
||||
void LazyListViewAttached::setTrackViewport(bool track) {
|
||||
if (m_trackViewport == track)
|
||||
return;
|
||||
m_trackViewport = track;
|
||||
emit trackViewportChanged();
|
||||
}
|
||||
|
||||
// --- LazyListView ---
|
||||
|
||||
LazyListView::LazyListView(QQuickItem* parent)
|
||||
|
|
@ -628,11 +639,21 @@ void LazyListView::syncDelegates() {
|
|||
if (entry.item) {
|
||||
const qreal h = delegateHeight(entry.item);
|
||||
if (!m_layout[i].heightKnown || !qFuzzyCompare(m_layout[i].height + 1.0, h + 1.0)) {
|
||||
const qreal oldLayoutH = m_layout[i].heightKnown ? m_layout[i].height : effectiveEstimatedHeight();
|
||||
if (m_layout[i].heightKnown)
|
||||
untrackHeight(m_layout[i].height);
|
||||
m_layout[i].height = h;
|
||||
m_layout[i].heightKnown = true;
|
||||
trackHeight(h);
|
||||
|
||||
// Compensate if tracked item materializes above viewport
|
||||
auto* att =
|
||||
qobject_cast<LazyListViewAttached*>(qmlAttachedPropertiesObject<LazyListView>(entry.item, false));
|
||||
if (att && att->trackViewport()) {
|
||||
const qreal vpTop = m_useCustomViewport ? m_viewport.y() : m_contentY;
|
||||
if (m_layout[i].targetY < vpTop)
|
||||
emit viewportAdjustNeeded(h - oldLayoutH);
|
||||
}
|
||||
layoutChanged = true;
|
||||
}
|
||||
entry.item->setY(m_layout[i].targetY - m_contentY);
|
||||
|
|
@ -745,6 +766,18 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
|||
if (wasKnown)
|
||||
untrackHeight(oldH);
|
||||
trackHeight(h);
|
||||
|
||||
// If this tracked item is above the viewport, emit a
|
||||
// compensation delta so the consumer can adjust scroll.
|
||||
if (wasKnown) {
|
||||
auto* att = qobject_cast<LazyListViewAttached*>(qmlAttachedPropertiesObject<LazyListView>(item, false));
|
||||
if (att && att->trackViewport()) {
|
||||
const qreal vpTop = m_useCustomViewport ? m_viewport.y() : m_contentY;
|
||||
if (m_layout[idx].targetY < vpTop)
|
||||
emit viewportAdjustNeeded(h - oldH);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_relayoutPending) {
|
||||
m_relayoutPending = true;
|
||||
QTimer::singleShot(0, this, [this] {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class LazyListViewAttached : public QObject {
|
|||
Q_PROPERTY(qreal visibleHeight READ visibleHeight WRITE setVisibleHeight NOTIFY visibleHeightChanged)
|
||||
Q_PROPERTY(bool adding READ adding NOTIFY addingChanged)
|
||||
Q_PROPERTY(bool removing READ removing NOTIFY removingChanged)
|
||||
Q_PROPERTY(bool trackViewport READ trackViewport WRITE setTrackViewport NOTIFY trackViewportChanged)
|
||||
|
||||
public:
|
||||
explicit LazyListViewAttached(QObject* parent = nullptr);
|
||||
|
|
@ -37,17 +38,22 @@ public:
|
|||
[[nodiscard]] bool removing() const;
|
||||
void setRemoving(bool removing);
|
||||
|
||||
[[nodiscard]] bool trackViewport() const;
|
||||
void setTrackViewport(bool track);
|
||||
|
||||
signals:
|
||||
void preferredHeightChanged();
|
||||
void visibleHeightChanged();
|
||||
void addingChanged();
|
||||
void removingChanged();
|
||||
void trackViewportChanged();
|
||||
|
||||
private:
|
||||
qreal m_preferredHeight = -1;
|
||||
qreal m_visibleHeight = -1;
|
||||
bool m_adding = false;
|
||||
bool m_removing = false;
|
||||
bool m_trackViewport = false;
|
||||
};
|
||||
|
||||
class LazyListView : public QQuickItem {
|
||||
|
|
@ -198,6 +204,7 @@ signals:
|
|||
void moveCurveChanged();
|
||||
void countChanged();
|
||||
void settledChanged();
|
||||
void viewportAdjustNeeded(qreal delta);
|
||||
|
||||
protected:
|
||||
void componentComplete() override;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue