Flutter使用Hero实现Text组件样式过渡时动画卡顿如何正确实现?
Hero组件Text字号平滑过渡实现方案
问题原因
默认Hero过渡动画执行期间,框架仅对共享组件的位置、外轮廓尺寸做插值计算,不会对Text内部的样式属性(如fontSize、color、fontWeight)做逐帧插值,因此会出现动画前半段沿用源页面样式、后半段直接跳转为目标页面样式的卡顿表现。
最优实现方案(官方推荐)
通过Hero的flightShuttleBuilder参数自定义过渡期间的展示组件,手动对字号等样式属性做动画插值,具体实现如下:
- 首先保证两个页面的Hero组件设置完全相同的tag值,这是Hero组件匹配共享元素的基础
- 为其中任意一个Hero组件实现
flightShuttleBuilder逻辑,通过Animation驱动样式插值:
// 源页面代码 Hero( tag: "custom_text_tag", // 两端tag必须完全一致 child: Text( "共享文本内容", style: TextStyle(fontSize: 16, color: Colors.black), ), ); // 目标页面代码 Hero( tag: "custom_text_tag", // 和源页面tag保持一致 flightShuttleBuilder: ( BuildContext flightContext, Animation<double> animation, HeroFlightDirection direction, BuildContext fromHeroContext, BuildContext toHeroContext, ) { // 自动获取两端Text的样式,无需硬编码 final fromText = (fromHeroContext.widget as Hero).child as Text; final toText = (toHeroContext.widget as Hero).child as Text; final beginSize = fromText.style?.fontSize ?? 14; final endSize = toText.style?.fontSize ?? 24; final beginColor = fromText.style?.color ?? Colors.black; final endColor = toText.style?.color ?? Colors.black; return AnimatedBuilder( animation: animation, builder: (context, child) { return Text( fromText.data ?? "", style: TextStyle( fontSize: Tween<double>(begin: beginSize, end: endSize).animate(animation).value, color: ColorTween(begin: beginColor, end: endColor).animate(animation).value, // 其余需要平滑过渡的样式都可以在此处添加对应Tween插值 ), ); }, ); }, child: Text( "共享文本内容", style: TextStyle(fontSize: 24, color: Colors.blueAccent), ), );
注意事项
- 两端Text的文本内容必须完全一致,否则过渡时会出现内容跳变
- 如果有自定义fontFamily等属性,需要保证两端的字体资源已提前加载,避免过渡时出现字体闪烁
- 不要在Hero的child外层嵌套多余的无约束容器,避免过渡时位置计算出现偏移
内容的提问来源于stack exchange,提问作者user6097845
相关产品推荐
相关产品推荐

