fix: use visible height to calc contentHeight
This commit is contained in:
parent
051b8caee6
commit
916b702562
3 changed files with 59 additions and 4 deletions
|
|
@ -73,6 +73,7 @@ LazyListView {
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyListView.preferredHeight: closed ? 0 : notifInner.nonAnimHeight
|
LazyListView.preferredHeight: closed ? 0 : notifInner.nonAnimHeight
|
||||||
|
LazyListView.visibleHeight: notifInner.implicitHeight
|
||||||
implicitHeight: notifInner.implicitHeight
|
implicitHeight: notifInner.implicitHeight
|
||||||
|
|
||||||
opacity: LazyListView.removing || closed || LazyListView.adding ? 0 : 1
|
opacity: LazyListView.removing || closed || LazyListView.adding ? 0 : 1
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,17 @@ void LazyListViewAttached::setPreferredHeight(qreal height) {
|
||||||
emit preferredHeightChanged();
|
emit preferredHeightChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qreal LazyListViewAttached::visibleHeight() const {
|
||||||
|
return m_visibleHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyListViewAttached::setVisibleHeight(qreal height) {
|
||||||
|
if (qFuzzyCompare(m_visibleHeight, height))
|
||||||
|
return;
|
||||||
|
m_visibleHeight = height;
|
||||||
|
emit visibleHeightChanged();
|
||||||
|
}
|
||||||
|
|
||||||
bool LazyListViewAttached::adding() const {
|
bool LazyListViewAttached::adding() const {
|
||||||
return m_adding;
|
return m_adding;
|
||||||
}
|
}
|
||||||
|
|
@ -210,6 +221,22 @@ qreal LazyListView::delegateHeight(QQuickItem* item) {
|
||||||
return item->implicitHeight();
|
return item->implicitHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qreal LazyListView::delegateVisibleHeight(QQuickItem* item) {
|
||||||
|
if (!item)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto* attached = qobject_cast<LazyListViewAttached*>(
|
||||||
|
qmlAttachedPropertiesObject<LazyListView>(item, false));
|
||||||
|
if (attached) {
|
||||||
|
if (attached->visibleHeight() >= 0)
|
||||||
|
return attached->visibleHeight();
|
||||||
|
if (attached->preferredHeight() >= 0)
|
||||||
|
return attached->preferredHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
return item->implicitHeight();
|
||||||
|
}
|
||||||
|
|
||||||
// --- Add Animation ---
|
// --- Add Animation ---
|
||||||
|
|
||||||
int LazyListView::addDuration() const {
|
int LazyListView::addDuration() const {
|
||||||
|
|
@ -388,15 +415,33 @@ void LazyListView::updatePolish() {
|
||||||
// --- Layout Engine ---
|
// --- Layout Engine ---
|
||||||
|
|
||||||
void LazyListView::relayout() {
|
void LazyListView::relayout() {
|
||||||
|
// Layout positioning uses preferredHeight (final/non-animated)
|
||||||
qreal y = 0;
|
qreal y = 0;
|
||||||
for (auto& record : m_layout) {
|
for (auto& record : m_layout) {
|
||||||
record.targetY = y;
|
record.targetY = y;
|
||||||
y += (record.heightKnown ? record.height : effectiveEstimatedHeight()) + m_spacing;
|
y += (record.heightKnown ? record.height : effectiveEstimatedHeight()) + m_spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
const qreal newHeight = m_layout.isEmpty() ? 0 : y - m_spacing;
|
// Content height tracks actual visible heights so scrolling follows animations
|
||||||
if (!qFuzzyCompare(m_contentHeight, newHeight)) {
|
qreal visY = 0;
|
||||||
m_contentHeight = newHeight;
|
for (int i = 0; i < static_cast<int>(m_layout.size()); ++i) {
|
||||||
|
qreal h;
|
||||||
|
if (m_delegates.contains(i) && m_delegates[i].item)
|
||||||
|
h = delegateVisibleHeight(m_delegates[i].item);
|
||||||
|
else
|
||||||
|
h = m_layout[i].heightKnown ? m_layout[i].height : effectiveEstimatedHeight();
|
||||||
|
visY += h + m_spacing;
|
||||||
|
}
|
||||||
|
qreal maxBottom = m_layout.isEmpty() ? 0 : visY - m_spacing;
|
||||||
|
|
||||||
|
// Account for dying delegates still visually present
|
||||||
|
for (const auto& dying : m_dyingDelegates) {
|
||||||
|
if (dying.item)
|
||||||
|
maxBottom = std::max(maxBottom, dying.item->y() + delegateVisibleHeight(dying.item));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qFuzzyCompare(m_contentHeight, maxBottom)) {
|
||||||
|
m_contentHeight = maxBottom;
|
||||||
emit contentHeightChanged();
|
emit contentHeightChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -591,12 +636,14 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
||||||
// Watch implicitHeight as fallback
|
// Watch implicitHeight as fallback
|
||||||
connect(entry.item, &QQuickItem::implicitHeightChanged, this, onHeightChanged);
|
connect(entry.item, &QQuickItem::implicitHeightChanged, this, onHeightChanged);
|
||||||
|
|
||||||
// Watch attached preferredHeight if the delegate uses it
|
// Watch attached properties if the delegate uses them
|
||||||
auto* attached = qobject_cast<LazyListViewAttached*>(
|
auto* attached = qobject_cast<LazyListViewAttached*>(
|
||||||
qmlAttachedPropertiesObject<LazyListView>(entry.item, false));
|
qmlAttachedPropertiesObject<LazyListView>(entry.item, false));
|
||||||
if (attached) {
|
if (attached) {
|
||||||
entry.attachedConnection = connect(attached, &LazyListViewAttached::preferredHeightChanged,
|
entry.attachedConnection = connect(attached, &LazyListViewAttached::preferredHeightChanged,
|
||||||
this, onHeightChanged);
|
this, onHeightChanged);
|
||||||
|
connect(attached, &LazyListViewAttached::visibleHeightChanged,
|
||||||
|
this, [this] { polish(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class LazyListViewAttached : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(qreal preferredHeight READ preferredHeight WRITE setPreferredHeight NOTIFY preferredHeightChanged)
|
Q_PROPERTY(qreal preferredHeight READ preferredHeight WRITE setPreferredHeight NOTIFY preferredHeightChanged)
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
@ -27,6 +28,9 @@ public:
|
||||||
[[nodiscard]] qreal preferredHeight() const;
|
[[nodiscard]] qreal preferredHeight() const;
|
||||||
void setPreferredHeight(qreal height);
|
void setPreferredHeight(qreal height);
|
||||||
|
|
||||||
|
[[nodiscard]] qreal visibleHeight() const;
|
||||||
|
void setVisibleHeight(qreal height);
|
||||||
|
|
||||||
[[nodiscard]] bool adding() const;
|
[[nodiscard]] bool adding() const;
|
||||||
void setAdding(bool adding);
|
void setAdding(bool adding);
|
||||||
|
|
||||||
|
|
@ -35,11 +39,13 @@ public:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void preferredHeightChanged();
|
void preferredHeightChanged();
|
||||||
|
void visibleHeightChanged();
|
||||||
void addingChanged();
|
void addingChanged();
|
||||||
void removingChanged();
|
void removingChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
qreal m_preferredHeight = -1;
|
qreal m_preferredHeight = -1;
|
||||||
|
qreal m_visibleHeight = -1;
|
||||||
bool m_adding = false;
|
bool m_adding = false;
|
||||||
bool m_removing = false;
|
bool m_removing = false;
|
||||||
};
|
};
|
||||||
|
|
@ -209,6 +215,7 @@ private:
|
||||||
[[nodiscard]] QRectF effectiveViewport() const;
|
[[nodiscard]] QRectF effectiveViewport() const;
|
||||||
[[nodiscard]] qreal effectiveEstimatedHeight() const;
|
[[nodiscard]] qreal effectiveEstimatedHeight() const;
|
||||||
[[nodiscard]] static qreal delegateHeight(QQuickItem* item);
|
[[nodiscard]] static qreal delegateHeight(QQuickItem* item);
|
||||||
|
[[nodiscard]] static qreal delegateVisibleHeight(QQuickItem* item);
|
||||||
void trackHeight(qreal height);
|
void trackHeight(qreal height);
|
||||||
void untrackHeight(qreal height);
|
void untrackHeight(qreal height);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue