HarmonyOS 鸿蒙Next中App设置了字体跟随系统,切换系统字体大小后,lottie动画出现问题
HarmonyOS 鸿蒙Next中App设置了字体跟随系统,切换系统字体大小后,lottie动画出现问题 ↓正常的状态

↓修改系统字体后,回到应用,lottie动画异常

配置如下
AppScope/resources/base/profile/configuration.json
{
"configuration": {
"fontSizeScale": "followSystem"
}
}
组件UI大致实现如下
// lottie动画在 Tab -> TabContent -> tabBar 里面
// tabBar 使用一个 @Builder 来构建
// 这个 build 内部实现如下:
Badge() {
Stack() {
Image()
Canvas(this.canvasRenderingCtx)
.width("24vp")
.height("24vp")
.onReady(() => {
this.animateItem?.resize()
this.loadLottieJson(tabIdx)
})
.onDisAppear(() => {
lottie.destroy('tabIdx')
})
}
...
}
// 其中 读取并运行lottie动画的函数 this.loadLottieJson() 实现如下
loadLottieJson(idx: number) {
MyLottieDataList.forEach((item, idx) => {
if (tabIdx == idx) {
let appId = item.appId
lottie.destroy(appId)
this.animateItem = lottie.loadAnimation({
container: this.canvasRenderingCtx,
renderer: 'canvas',
loop: false,
autoplay: false,
name: appId,
autoSkip: false,
path: `lottieJSON/${item.lottieJson}`
})
this.animateItem.addEventListener('DOMLoaded', (args: Object): void => {
if (this.animateItem) {
this.animateItem.play();
}
});
}
})
}
这个动画在平时使用过程中没有任何问题,但是一旦执行以下步骤 “应用退到后台 -> 修改系统字体大小 -> 应用回到前台”,tab上的 lottie 就变白了,只有切换tabbar 才会恢复正常
我尝试过在 onPageShow() 加一个延时,重新执行 loadLottieJson 函数,想让动画重新执行一遍。
在普通的应用“退到后台 -> 回到前台”时,该操作生效。
但是在 “应用退到后台 -> 修改系统字体大小 -> 应用回到前台”时,动画不生效。
更多关于HarmonyOS 鸿蒙Next中App设置了字体跟随系统,切换系统字体大小后,lottie动画出现问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
开发者你好,当前根据您这边的场景描述进行了代码配置,在进行了 “应用退到后台 -> 修改系统字体大小 -> 应用回到前台”操作时,并未出现你这边截图中的异常现象,请问是否可以提供下最小复现问题的代码。
import lottie, { AnimationItem } from '@ohos/lottie';
@Entry
@Component
struct PageDemo {
private renderingSettings: RenderingContextSettings = new RenderingContextSettings(true);
private canvasRenderingContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.renderingSettings);
private animateItem: AnimationItem | null = null;
private animateName: string = 'animation';
build() {
Column() {
Tabs() {
TabContent() {
// app.string.homepage_content资源文件中的value值为“首页的内容”
Text($r('app.string.homepage_content'))
.fontSize(30)
}
// app.string.homepage资源文件中的value值为“首页”
.tabBar($r('app.string.homepage'))
TabContent() {
// app.string.recommend_content资源文件中的value值为“推荐的内容”
Text($r('app.string.recommend_content'))
.fontSize(30)
}
// app.string.recommend资源文件中的value值为“推荐”
.tabBar($r('app.string.recommend'))
TabContent() {
// app.string.discover_content资源文件中的value值为“发现的内容”
Text($r('app.string.discover_content'))
.fontSize(30)
}
// app.string.discover资源文件中的value值为“发现”
.tabBar($r('app.string.discover'))
TabContent() {
// app.string.mine_content资源文件中的value值为“我的内容”
Text($r('app.string.mine_content'))
.fontSize(30)
}
// app.string.mine_content资源文件中的value值为“我的”
.tabBar(this.tabBuilder(4))
}
}
}
@Builder
tabBuilder(num:number) {
Badge({count:num, style: { badgeSize: 6, badgeColor: '#FA2A2D' }}) {
Stack() {
Column(){
Image($r("app.media.startIcon"))
.width(30)
.height(30)
Text("我的")
}
Canvas(this.canvasRenderingContext)
.width("24vp")
.height("24vp")
.onReady(() => {
this.animateItem?.resize()
this.loadAnimation()
})
.onDisAppear(() => {
lottie.destroy('tabIdx')
})
}
}
}
loadAnimation() {
this.animateItem = lottie.loadAnimation({
container: this.canvasRenderingContext,
renderer: 'canvas', // canvas 渲染模式
loop: false,
autoplay: false,
name: this.animateName,
autoSkip:false,
contentMode: 'Contain',
path: 'common/animation.json',
})
// 因为动画是异步加载,所以对animateItem的操作需要放在动画加载完成回调里操作
this.animateItem?.addEventListener('DOMLoaded', (args: Object): void => {
this.animateItem?.changeColor([225, 25, 100, 1]);
this.animateItem?.play();
});
}
}
更多关于HarmonyOS 鸿蒙Next中App设置了字体跟随系统,切换系统字体大小后,lottie动画出现问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
你这个代码你真的运行过么?我这还是报错的,修改字体从后台回到前台之后,即使加上你的DOMLoaded依然是无法播放,都不会走监听回调,lottile库版本是
@ohos/lottie@2.0.30

onConfigurationUpdate
当系统全局配置(例如系统语言、深浅色等)发生变更时,会触发该回调。
// EntryAbility.ets
onConfigurationUpdate(config: Configuration): void {
console.info(`EntryAbility.onConfigurationUpdate, colorMode: ${config.colorMode}`);
console.info(`EntryAbility.onConfigurationUpdate, fontSizeScale: ${config.fontSizeScale}`);
this.context.eventHub.emit("onConfigurationUpdate", config);
}
所在页面
@Entry
@ComponentV2
struct Demo {
private onConfigurationUpdate = (config?: Configuration) => {
//重新执行 loadLottieJson 函数
};
aboutToAppear(): void {
this.getUIContext().getHostContext()?.eventHub.on("onConfigurationUpdate", this.onConfigurationUpdate);
}
aboutToDisappear(): void {
this.getUIContext().getHostContext()?.eventHub.off("onConfigurationUpdate", this.onConfigurationUpdate);
}
build() {
//...
}
}
试试看行不行。
在鸿蒙Next中,系统字体缩放会动态调整应用的字体大小。Lottie动画若包含文本图层(如动态文本或SVG渲染),其尺寸计算依赖初始字体上下文,切换后可能未及时更新,导致布局偏移、闪烁或变形。另外,字体缩放可能影响Canvas或渲染管线中的矩阵变换,造成动画帧异常。,
你遇到的Lottie动画在系统字体变更后变白的问题,通常是因为系统配置变更触发了页面或组件的重建,导致 Canvas 绘图上下文失效,但 Lottie 仍在使用旧的、无效的渲染上下文。
在你的场景中,“退后台->改字体->回前台”这个操作,系统为了适配新的字体缩放比例,可能会销毁并重建当前页面。Canvas 组件被重新创建,其持有的 canvasRenderingCtx 变成了新的对象,但 loadLottieJson 可能在旧上下文中被触发或依然持有旧上下文的引用,导致渲染为空白。
你尝试在 onPageShow 中重载动画,但普通前后台切换与配置变更导致的页面重建生命周期是不同的,所以单独延时重载在后者场景下未生效。
解决方法的核心是:当 Canvas 重建后,确保在它的 onReady 回调里重新加载 Lottie 动画,因为此时传入的 context 是崭新且有效的。
你可以按如下方式修改 TabBar 构建器内的 Canvas 代码:
// 在 TabBar 的 @Builder 中
Badge() {
Stack() {
Image()
Canvas(this.canvasRenderingCtx) // 确保上下文引用已更新
.width("24vp")
.height("24vp")
.onReady(() => {
// Canvas 准备就绪,包括首次创建和配置变更后重建。
// 在这里销毁旧动画并加载新动画,保证使用的是当前有效的 context。
if (this.animateItem) {
lottie.destroy(this.currentAppId); // 销毁可能存在的旧实例
}
// 关键:在此回调中加载动画,this 指向当前组件实例,上下文是最新的。
this.loadLottieJson(this.currentTabIdx);
})
.onDisAppear(() => {
lottie.destroy(this.currentAppId);
})
}
}
同时,确保 loadLottieJson 函数直接使用传入的参数或组件当前状态,不再依赖外部的延时重试。这样,无论是正常创建还是因字体变更导致的重建,都能在 Canvas 就绪时正确加载动画,从根本上解决问题。



