From 89f1df9a9bbe131798893cffe0ac642768b3d867 Mon Sep 17 00:00:00 2001 From: fengge <844143714@qq.com> Date: Wed, 3 Jun 2026 14:48:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96(UI):=20=E4=BF=AE=E5=A4=8D=20?= =?UTF-8?q?Compose=20=E7=9A=84=E6=82=AC=E6=B5=AE=E7=AA=97=E7=81=BE?= =?UTF-8?q?=E9=9A=BE=E6=80=A7=E9=87=8D=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 利用延迟读取(Deferred State Reading)的特性,将 fabOffsetX 等坐标变量的读取放置在 Modifier.offset 的 lambda 内部。 这样拖动悬浮窗时,只会触发 Compose 的布局阶段(Layout phase)刷新,而不再引发整个组件的无效重组(Recomposition),彻底解决在低端机上拖动严重掉帧和 CPU 占用的问题。 --- .../standapp/ui/chat/FloatingChatWidget.kt | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/stand/standapp/ui/chat/FloatingChatWidget.kt b/app/src/main/java/com/stand/standapp/ui/chat/FloatingChatWidget.kt index 42585f5..84dcd91 100644 --- a/app/src/main/java/com/stand/standapp/ui/chat/FloatingChatWidget.kt +++ b/app/src/main/java/com/stand/standapp/ui/chat/FloatingChatWidget.kt @@ -94,25 +94,19 @@ fun FloatingChatWidget() { visible = true } - // 👈 用 FAB 位置计算对话框位置,但强制钳制在屏幕内 - // FAB右下角为基准:对话框应该出现在 FAB 附近 - val fabRight = screenWidthPx - paddingPx * 2 + fabOffsetX // FAB右边缘 - val fabBottom = screenHeightPx - paddingPx * 2 - navBarPx + fabOffsetY // FAB下边缘 - - // 对话框优先放在 FAB 左上方,如果放不下就贴边 - val rawX = fabRight - cardWidthPx - paddingPx // FAB左边 - val rawY = fabBottom - cardHeightPx - paddingPx // FAB上边 - - // 👈 关键:钳制到屏幕内 - val clampedX = rawX.coerceIn(0f, screenWidthPx - cardWidthPx) - val clampedY = rawY.coerceIn(0f, screenHeightPx - cardHeightPx) - AnimatedVisibility( visible = visible, enter = fadeIn(animationSpec = tween(300)) + scaleIn(initialScale = 0.8f, animationSpec = tween(300)), exit = fadeOut(animationSpec = tween(200)) + scaleOut(targetScale = 0.8f, animationSpec = tween(200)), modifier = Modifier .offset { + val fabRight = screenWidthPx - paddingPx * 2 + fabOffsetX + val fabBottom = screenHeightPx - paddingPx * 2 - navBarPx + fabOffsetY + val rawX = fabRight - cardWidthPx - paddingPx + val rawY = fabBottom - cardHeightPx - paddingPx + val clampedX = rawX.coerceIn(0f, screenWidthPx - cardWidthPx) + val clampedY = rawY.coerceIn(0f, screenHeightPx - cardHeightPx) + IntOffset( (clampedX + cardDragX).roundToInt() .coerceIn(0, (screenWidthPx - cardWidthPx).toInt()),