From 53e2687546b65c002175634a612ccd8fac6b9744 Mon Sep 17 00:00:00 2001 From: xlj <543978819@qq.com> Date: Wed, 13 Aug 2025 12:55:27 +0800 Subject: [PATCH] update --- .../ui/components/ChatContentsLayout.ts | 39 +++++++-- .../chat18x/ui/components/DialogBubble.ts | 85 ++++++++++--------- assets/Scripts/chat18x/ui/panels/ChatPanel.ts | 5 +- assets/bundles/Chat18x/ChatPanel.prefab | 18 ++-- 4 files changed, 89 insertions(+), 58 deletions(-) diff --git a/assets/Scripts/chat18x/ui/components/ChatContentsLayout.ts b/assets/Scripts/chat18x/ui/components/ChatContentsLayout.ts index 69caf56b..3b4a8d59 100644 --- a/assets/Scripts/chat18x/ui/components/ChatContentsLayout.ts +++ b/assets/Scripts/chat18x/ui/components/ChatContentsLayout.ts @@ -39,9 +39,22 @@ export class ChatContentsLayout extends Component { } this.bubbles = []; + this.updateDialogLayout(dialogs); + + // 清理多余的缓存气泡,避免内存泄漏 + this.cleanupExcessCachedBubbles(); + } + + private updateDialogLayout(dialogs: Dialog[]) { let initPosY: number = BUTTOM_Y; - for (let i = dialogs.length - 1; i >= 0; i--) { - const dialog = dialogs[i]; //倒序 + let pendingUpdates = 0; + + const updateNextBubble = (index: number) => { + if (index < 0) { + return; + } + + const dialog = dialogs[index]; let newBubble: DialogBubble = null; // 尝试从缓存中获取合适的气泡 @@ -69,17 +82,25 @@ export class ChatContentsLayout extends Component { } newBubble.node.active = true; - let offset = newBubble.updateBubbleContent(dialog.content); - let pos = newBubble.node.position; newBubble.node.position = new Vec3(pos.x, initPosY, pos.z); - - initPosY += offset + 20; + + pendingUpdates++; + newBubble.updateBubbleContent(dialog.content, (actualHeight: number) => { + initPosY += actualHeight + 20; + pendingUpdates--; + + // 当当前气泡更新完成后,处理下一个 + if (pendingUpdates === 0) { + updateNextBubble(index - 1); + } + }); + this.bubbles.push(newBubble); - } + }; - // 清理多余的缓存气泡,避免内存泄漏 - this.cleanupExcessCachedBubbles(); + // 从最后一个对话开始处理(倒序) + updateNextBubble(dialogs.length - 1); } private cleanupExcessCachedBubbles() { diff --git a/assets/Scripts/chat18x/ui/components/DialogBubble.ts b/assets/Scripts/chat18x/ui/components/DialogBubble.ts index 47290f73..f121c428 100644 --- a/assets/Scripts/chat18x/ui/components/DialogBubble.ts +++ b/assets/Scripts/chat18x/ui/components/DialogBubble.ts @@ -11,47 +11,54 @@ export class DialogBubble extends Component { @property(UITransform) contentT: UITransform = null; - updateBubbleContent(str: string) { - const lines = str.split("\n"); - let len = 0; - let index = 0; - for (let i = 0; i < lines.length; i++) { - const element = lines[i]; - if (element.length > len) { - len = element.length; - index = i; - } - } - - let finalLen = 0; - // for (let i = 0; i < lines[index].length; i++) { - // const element = lines[index][i]; - // if ("\u4e00" <= element[i] && element[i] <= "\u9fff") { - // finalLen += 35; - // } else { - // finalLen += 18; - // } - // } - - if (Tools.IsChinese(lines[index])) { - finalLen = 35 * lines[index].length; - } else { - finalLen = 21 * lines[index].length; - } - + updateBubbleContent(str: string, callback?: (actualHeight: number) => void) { + // 设置文本内容 this.content.string = str; - this.contentT.setContentSize( - new Size(Math.min(finalLen, 950), this.contentT.contentSize.y) - ); - this.content.updateRenderData(); - this.bg.setContentSize( - new Size( - this.contentT.contentSize.x + 30, - this.contentT.contentSize.y + 20 - ) - ); + // 计算最大宽度(估算) + const lines = str.split("\n"); + let maxWidth = 0; - return this.bg.contentSize.y; + for (const line of lines) { + let lineWidth = 0; + if (Tools.IsChinese(line)) { + lineWidth = 35 * line.length; + } else { + lineWidth = 21 * line.length; + } + maxWidth = Math.max(maxWidth, lineWidth); + } + + // 限制最大宽度 + const contentWidth = Math.min(maxWidth, 950); + + // 设置内容区域宽度,让Label自动计算高度 + this.contentT.setContentSize(new Size(contentWidth, 0)); + this.bg.setContentSize(new Size(contentWidth + 20, 0)); + + // 强制更新Label的渲染数据以获取正确的高度 + this.content.updateRenderData(true); + + // 等待一帧后获取Label的实际高度 + this.scheduleOnce(() => { + const actualHeight = + this.content.node.getComponent(UITransform).contentSize.height; + + // 更新内容区域的实际大小 + this.contentT.setContentSize(new Size(contentWidth, actualHeight)); + + // 根据内容大小调整背景大小,添加适当的内边距 + const bgHeight = actualHeight + 20; + this.bg.setContentSize(new Size(contentWidth + 50, bgHeight)); + + // 回调通知实际高度 + if (callback) { + callback(bgHeight); + } + }, 0); + + // 返回预估的背景高度(用于同步计算) + const estimatedHeight = Math.max(lines.length * 35 + 20, 60); // 最小高度60 + return estimatedHeight; } } diff --git a/assets/Scripts/chat18x/ui/panels/ChatPanel.ts b/assets/Scripts/chat18x/ui/panels/ChatPanel.ts index c82e3cd0..2b04c246 100644 --- a/assets/Scripts/chat18x/ui/panels/ChatPanel.ts +++ b/assets/Scripts/chat18x/ui/panels/ChatPanel.ts @@ -76,6 +76,7 @@ export class ChatPanel extends li_BaseView { Utils.addInnerEL(InnerMsgCode.LanguageChange, this, this.onLanguageChangeCallback); } onDestroy(): void { + Utils.removeInnerEL(InnerMsgCode.Chat_DialogRefresh, this, this.onDialogUpdate); Utils.removeInnerEL(InnerMsgCode.LanguageChange, this, this.onLanguageChangeCallback); } refresh(id: number) { @@ -107,7 +108,9 @@ export class ChatPanel extends li_BaseView { }); } onDialogUpdate() { - this.layout.UpdateDialog(DialogManager.getInstance().getDialogs()); + if (this.layout) { + this.layout.UpdateDialog(DialogManager.getInstance().getDialogs()); + } } protected onEnable(): void { if (!this.manager) this.manager = DialogManager.getInstance(); diff --git a/assets/bundles/Chat18x/ChatPanel.prefab b/assets/bundles/Chat18x/ChatPanel.prefab index 65092f9a..775fcd34 100644 --- a/assets/bundles/Chat18x/ChatPanel.prefab +++ b/assets/bundles/Chat18x/ChatPanel.prefab @@ -2327,7 +2327,7 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 35, + "width": 37.399993896484375, "height": 44.352000000000004 }, "_anchorPoint": { @@ -2366,8 +2366,8 @@ "_string": "慵", "_horizontalAlign": 0, "_verticalAlign": 1, - "_actualFontSize": 35, - "_fontSize": 35, + "_actualFontSize": 37.4, + "_fontSize": 37.4, "_fontFamily": "NotoSans-Regular", "_lineHeight": 35.2, "_overflow": 3, @@ -3002,7 +3002,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": -20, - "y": 67.376, + "y": 32.176, "z": 0 }, "_lrot": { @@ -3042,8 +3042,8 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 435.786523, - "height": 114.752 + "width": 247.62884521484375, + "height": 44.352000000000004 }, "_anchorPoint": { "__type__": "cc.Vec2", @@ -3078,11 +3078,11 @@ "b": 5, "a": 255 }, - "_string": "asdasddsasdasdadasdasdasdasdasdasdasdadasdasdasdas", + "_string": "asdasddsasda", "_horizontalAlign": 0, "_verticalAlign": 1, - "_actualFontSize": 35, - "_fontSize": 35, + "_actualFontSize": 37.4, + "_fontSize": 37.4, "_fontFamily": "NotoSans-Regular", "_lineHeight": 35.2, "_overflow": 3,