From 297e7e9e787c5ecb5bb338585b3ee13af7bcdceb Mon Sep 17 00:00:00 2001 From: chenyuanbo Date: Mon, 13 Jul 2026 17:36:55 +0800 Subject: [PATCH] fix: fix bubble list layout update on height change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the remove/insert workaround with `replace` + `dataChanged` and handle height recalculations properly by toggling displayMarginBeginning. The old approach of removing and inserting items forced delegate recreation but caused unnecessary overhead and potential visual glitches. The new approach uses QList::replace() which is more efficient, but requires explicit handling of height updates because the view's transition logic can prevent proper re-layout when an item's height changes during a running transition. Influence: 1. Test notification bubble replacement in normal scenarios 2. Test bubble height changes when content updates (e.g., expanding/ collapsing) 3. Verify no visual glitches during rapid notification updates 4. Test with multiple simultaneous notifications and transitions 5. Verify smooth scrolling behavior when bubble heights change 6. Test edge cases with very long notification messages fix: 修复气泡列表高度变化时布局更新问题 用 `replace` + `dataChanged` 替换移除/插入的变通方案,并通过切换 displayMarginBeginning 正确处理高度重新计算。旧方法通过移除和插入项目 强制 委托重建,但导致不必要的开销和潜在的视觉问题。新方法使用 QList::replace() 效率更高,但需要显式处理高度更新,因为视图的过渡逻辑可能会在运行过渡期间 阻止项目高度变化时的正确重新布局。 Influence: 1. 测试正常场景下的通知气泡替换 2. 测试内容更新时气泡高度的变化(如展开/折叠) 3. 验证快速更新通知时无视觉闪烁 4. 测试多个同时发生的通知和过渡 5. 验证气泡高度变化时滚动行为流畅 6. 测试超长通知消息的边界情况 PMS: BUG-367205 --- panels/notification/bubble/bubblemodel.cpp | 11 ++--------- panels/notification/bubble/package/main.qml | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/panels/notification/bubble/bubblemodel.cpp b/panels/notification/bubble/bubblemodel.cpp index 44382c4fe..c9bbee6fb 100644 --- a/panels/notification/bubble/bubblemodel.cpp +++ b/panels/notification/bubble/bubblemodel.cpp @@ -95,15 +95,8 @@ BubbleItem *BubbleModel::replaceBubble(BubbleItem *bubble) const auto replaceIndex = replaceBubbleIndex(bubble); const auto oldBubble = m_bubbles[replaceIndex]; - // Use remove + insert instead of dataChanged to force the view - // to recreate the delegate, so ListView recalculates its height. - beginRemoveRows(QModelIndex(), replaceIndex, replaceIndex); - m_bubbles.removeAt(replaceIndex); - endRemoveRows(); - - beginInsertRows(QModelIndex(), replaceIndex, replaceIndex); - m_bubbles.insert(replaceIndex, bubble); - endInsertRows(); + m_bubbles.replace(replaceIndex, bubble); + Q_EMIT dataChanged(index(replaceIndex), index(replaceIndex)); return oldBubble; } diff --git a/panels/notification/bubble/package/main.qml b/panels/notification/bubble/package/main.qml index e078ac4b6..69c3b0614 100644 --- a/panels/notification/bubble/package/main.qml +++ b/panels/notification/bubble/package/main.qml @@ -103,6 +103,17 @@ Window { bottomMargin: 10 } + // itemGeometryChanged() normally triggers forceLayoutPolish() to + // re-layout with updated height, but it exits early when a transition + // (add/remove/displaced) is running for the first visible item. + // Toggle displayMarginBeginning to force forceLayoutPolish() directly, + // bypassing the transition check. + function requestLayoutFix() { + var m = displayMarginBeginning + displayMarginBeginning = m + 1 + displayMarginBeginning = m + } + function updateInputRegion() { root.DLayerShellWindow.setInputRegionRect( Math.ceil(bubbleView.x), @@ -171,6 +182,14 @@ Window { delegate: BubbleDelegate { maxCount: model.bubbleCount + + onHeightChanged: { + if (index < 0) { + return + } + + bubbleView.requestLayoutFix() + } } } }