import { _decorator, Component, Label, Node, Overflow, Size, Sprite, UITransform, view, } from "cc"; import Tools from "../../utils/tools"; import { GirlData } from "../../data/GirlData"; import { DataId, DataManager } from "../../data/DataManager"; import { NavigationManager } from "../../manager/NavigationManager"; import ResManager from "../../../Main/Manager/ResManager"; import { EnvData } from "../../data/EnvData"; const { ccclass, property } = _decorator; @ccclass("DialogBubble") export class DialogBubble extends Component { @property(Sprite) avatar: Sprite = null; @property(UITransform) bg: UITransform = null; @property(Label) content: Label = null; @property(UITransform) contentT: UITransform = null; fixMaxWidth: number; uiTransform: UITransform; init(maxWidth?: number) { this.uiTransform = this.node.getComponent(UITransform); // 如果没有提供maxWidth,使用屏幕宽度的80% if (maxWidth === undefined) { this.fixMaxWidth = view.getVisibleSize().width * 0.8; } else { this.fixMaxWidth = maxWidth; } } updateBubbleContent( str: string, isPlayer: boolean = false, callback?: (actualHeight: number) => void, isLoading: boolean = false ) { // 停止之前的加载动画 this.stopLoadingAnimation(); this.content.overflow = Overflow.NONE; // 如果是加载状态,使用固定的"..." if (isLoading) { this.content.string = "..."; // 设置固定尺寸用于加载显示 const contentWidth = 60; this.contentT.setContentSize(new Size(contentWidth, 40)); this.bg.setContentSize(new Size(contentWidth + 30, 50)); if (callback) { callback(40); // 返回固定高度 } return; } // 设置文本内容 this.content.string = str; // 计算最大宽度(估算) const lines = str.split("\n"); let maxWidth = 0; for (const line of lines) { let lineWidth = 0; if (Tools.IsChinese(line)) { lineWidth = 30 * line.length; } else { lineWidth = 18 * line.length; } maxWidth = Math.max(maxWidth, lineWidth); } if (maxWidth > this.fixMaxWidth) this.content.overflow = Overflow.RESIZE_HEIGHT; // 限制最大宽度 const contentWidth = Math.min(maxWidth, this.fixMaxWidth); // 设置内容区域宽度,让Label自动计算高度 this.contentT.setContentSize(new Size(contentWidth, 0)); this.bg.setContentSize(new Size(contentWidth + 37, 0)); this.uiTransform.setContentSize(new Size(contentWidth + 37, 0)); // 强制更新Label的渲染数据以获取正确的高度 this.content.updateRenderData(true); // 等待一帧后获取Label的实际高度 this.scheduleOnce(() => { const actualSize = this.content.node.getComponent(UITransform).contentSize; // 更新内容区域的实际大小 //this.contentT.setContentSize(new Size(contentWidth, actualHeight)); // 根据内容大小调整背景大小,添加适当的内边距 //const bgHeight = actualHeight + 17; this.bg.setContentSize(new Size(actualSize.x + 40, actualSize.y + 30)); this.uiTransform.setContentSize( new Size(actualSize.x + 40, actualSize.y + 30) ); // 回调通知实际高度 if (callback) { callback(actualSize.y); } }, 0); // 返回预估的背景高度(用于同步计算) const estimatedHeight = Math.max(lines.length * 35 + 20, 60); // 最小高度60 //设置头像 if (isPlayer) { //获取玩家头像,等接入luffa } else { const girlData = DataManager.I.getDataById(DataId.Girl); const path = girlData.getGrilAvatar( NavigationManager.Instance.getSelectedCategoryId().toString(), NavigationManager.Instance.getSelectedGirlId() ); // 加载远程资源 const envData = DataManager.I.getDataById(DataId.Env); let newPath = envData.cdn + "/" + "Girls/" + path + ".png"; ResManager.I.changeRemoteSpriteFrame(this.avatar, newPath, () => {}); } return estimatedHeight; } private stopLoadingAnimation() { // 预留方法,当前实现中不需要动画,但保留接口以备将来使用 } }