cocos2 使用 Layout 组件后,子节点 Label 高度变化后,抖动问题
cocos2 使用 Layout 组件后,子节点 Label 高度变化后,抖动问题
最近使用 cocos2 做了一个简单的效果,就是类似于DeepSeek问答的效果,当然数据是写死的,没有对接接口,仅仅前端模拟而已。在做效果的时候发现一个问题,就是我在父容器中配置了Layout组件,按理说这个组件会自动布局的,但是我发现向子节点 Label 往里 push 文字的时候,在换行了的时候,布局会闪一下子,这篇文章主要解决这个问题。
问题
当我通过代码,每隔20毫秒的时候,向 Label 的 string 中追加一个字符,正常是没有问题的,但是当换行的时候,布局会抖动一下,就像下面的样子:
能看出来每当换行的时候会出现抖动的问题,可能截取GIF图,看的不是很明显,实际看起来很严重。
代码其实很简单:
this.timer = setInterval(() => {// 如果没有回答完则继续添加文字if (this.index < this.answerData.think.length) {// 向 label 中添加文字(关键代码!)txtNode.getComponent(cc.Label).string += this.answerData.think[this.index];this.index++; // 文字索引+1// 进度条划到最后面let chatBox = cc.find('Canvas/page/chatBox');chatBox.getComponent(cc.ScrollView).scrollToBottom(0.1);} else {// 回答完了就销毁定时器clearInterval(this.timer);this.timer = null;this.index = 0;}}, 25)
上面写了个案例代码,主要就是如果文字没有加载完,就每隔25毫秒向Label中添加一个文本进去。
原因
为啥会出现闪动的问题其实很显而易见,就是当换行了的时候,文本高度增加了,但是 Layout 没有立即响应,他需要下一帧才会渲染,所以说当子节点高度增加了,父元素高度还没来的急改变,子组件撑出父元素了,所以文本往上跑了,下一帧渲染的时候,父元素计算出了最新高度,父元素高度合适了,撑出去的子节点又回来了,平时不会撑出去,因为子节点高度不会变,只有子节点换行了,高度才会变化,才会出现这个问题。
解决
解决起来其实就几行代码,很简单。
就是当子节点高度发生变化的时候,我们手动强制刷新一下文本组件,然后在强制刷新一下需要重新布局父元素就可以了,代码也很简单:
// 文本强制刷新
txtNode.getComponent(cc.Label)._forceUpdateRenderData();
// 父节点强制刷新
thinkNode.getComponent(cc.Layout).updateLayout()
txtNode.getComponent(cc.Label)._forceUpdateRenderData();
解释:
txtNode
:一个CCNode
对象,表示文本标签所在的节点。getComponent(cc.Label)
:获取该节点上挂载的cc.Label
组件,用于显示文本_forceUpdateRenderData()
:强制更新标签的渲染数据。通常在修改文本内容后,引擎会自动更新渲染,但某些情况下(如立即需要获取文本宽度),需要手动强制刷新。_
前缀表示这是一个内部方法,不建议直接调用,但在必要时可用于优化渲染流程。
thinkNode.getComponent(cc.Layout).updateLayout();
解释:
thinkNode
:一个CCNode
对象,表示布局容器节点。getComponent(cc.Layout)
:获取该节点上挂载的cc.Layout
组件,用于自动排列子节updateLayout()
:立即更新布局。当动态添加、移除或调整子节点后,调用此方法触发布局重新计算,确保子节点按指定规则排列(如水平 / 垂直排列、网格等)。
这就可以了,如果套了好几层 Layout 布局的父节点,那个每一层父节点都要从里往外强制刷新一遍,这样就可以了。
这样就不会再出现闪动问题了,其实代码很简单,只不过不知道原因的话可能就需要卡住好久。
今天就到这里,拜了个拜!!!