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
|
cacheBuffer: 400
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
|
||||||
|
onViewportAdjustNeeded: d => container.contentY += d
|
||||||
useCustomViewport: true
|
useCustomViewport: true
|
||||||
viewport: Qt.rect(0, container.contentY, width, container.height)
|
viewport: Qt.rect(0, container.contentY, width, container.height)
|
||||||
|
|
||||||
|
|
@ -66,6 +67,7 @@ LazyListView {
|
||||||
clearTimer.start();
|
clearTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LazyListView.trackViewport: notifInner.expanded || notifInner.nonAnimHeight < notifInner.implicitHeight
|
||||||
LazyListView.preferredHeight: closed ? 0 : notifInner.nonAnimHeight
|
LazyListView.preferredHeight: closed ? 0 : notifInner.nonAnimHeight
|
||||||
LazyListView.visibleHeight: notifInner.implicitHeight
|
LazyListView.visibleHeight: notifInner.implicitHeight
|
||||||
implicitHeight: notifInner.implicitHeight
|
implicitHeight: notifInner.implicitHeight
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,17 @@ void LazyListViewAttached::setRemoving(bool removing) {
|
||||||
emit removingChanged();
|
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::LazyListView(QQuickItem* parent)
|
LazyListView::LazyListView(QQuickItem* parent)
|
||||||
|
|
@ -628,11 +639,21 @@ void LazyListView::syncDelegates() {
|
||||||
if (entry.item) {
|
if (entry.item) {
|
||||||
const qreal h = delegateHeight(entry.item);
|
const qreal h = delegateHeight(entry.item);
|
||||||
if (!m_layout[i].heightKnown || !qFuzzyCompare(m_layout[i].height + 1.0, h + 1.0)) {
|
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)
|
if (m_layout[i].heightKnown)
|
||||||
untrackHeight(m_layout[i].height);
|
untrackHeight(m_layout[i].height);
|
||||||
m_layout[i].height = h;
|
m_layout[i].height = h;
|
||||||
m_layout[i].heightKnown = true;
|
m_layout[i].heightKnown = true;
|
||||||
trackHeight(h);
|
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;
|
layoutChanged = true;
|
||||||
}
|
}
|
||||||
entry.item->setY(m_layout[i].targetY - m_contentY);
|
entry.item->setY(m_layout[i].targetY - m_contentY);
|
||||||
|
|
@ -745,6 +766,18 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
||||||
if (wasKnown)
|
if (wasKnown)
|
||||||
untrackHeight(oldH);
|
untrackHeight(oldH);
|
||||||
trackHeight(h);
|
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) {
|
if (!m_relayoutPending) {
|
||||||
m_relayoutPending = true;
|
m_relayoutPending = true;
|
||||||
QTimer::singleShot(0, this, [this] {
|
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(qreal visibleHeight READ visibleHeight WRITE setVisibleHeight NOTIFY visibleHeightChanged)
|
||||||
Q_PROPERTY(bool adding READ adding NOTIFY addingChanged)
|
Q_PROPERTY(bool adding READ adding NOTIFY addingChanged)
|
||||||
Q_PROPERTY(bool removing READ removing NOTIFY removingChanged)
|
Q_PROPERTY(bool removing READ removing NOTIFY removingChanged)
|
||||||
|
Q_PROPERTY(bool trackViewport READ trackViewport WRITE setTrackViewport NOTIFY trackViewportChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LazyListViewAttached(QObject* parent = nullptr);
|
explicit LazyListViewAttached(QObject* parent = nullptr);
|
||||||
|
|
@ -37,17 +38,22 @@ public:
|
||||||
[[nodiscard]] bool removing() const;
|
[[nodiscard]] bool removing() const;
|
||||||
void setRemoving(bool removing);
|
void setRemoving(bool removing);
|
||||||
|
|
||||||
|
[[nodiscard]] bool trackViewport() const;
|
||||||
|
void setTrackViewport(bool track);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void preferredHeightChanged();
|
void preferredHeightChanged();
|
||||||
void visibleHeightChanged();
|
void visibleHeightChanged();
|
||||||
void addingChanged();
|
void addingChanged();
|
||||||
void removingChanged();
|
void removingChanged();
|
||||||
|
void trackViewportChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
qreal m_preferredHeight = -1;
|
qreal m_preferredHeight = -1;
|
||||||
qreal m_visibleHeight = -1;
|
qreal m_visibleHeight = -1;
|
||||||
bool m_adding = false;
|
bool m_adding = false;
|
||||||
bool m_removing = false;
|
bool m_removing = false;
|
||||||
|
bool m_trackViewport = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LazyListView : public QQuickItem {
|
class LazyListView : public QQuickItem {
|
||||||
|
|
@ -198,6 +204,7 @@ signals:
|
||||||
void moveCurveChanged();
|
void moveCurveChanged();
|
||||||
void countChanged();
|
void countChanged();
|
||||||
void settledChanged();
|
void settledChanged();
|
||||||
|
void viewportAdjustNeeded(qreal delta);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void componentComplete() override;
|
void componentComplete() override;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue