页面导航时实现文本字体大小平滑过渡的问题
问题描述
- 需求:页面导航时实现文本字体大小的平滑过渡,例如Screen1中Text组件字号为14像素,Screen2中Text组件字号为18像素
- 问题:尝试结合Hero组件与TweenAnimationBuilder实现效果时,出现动画不流畅、导航过程中文本内容显示不全的问题
原代码
Screen1
Hero( tag: "animateTitle", child: Text( "Animated Text", style: context.headlineMedium?.copyWith( color: white.withOpacity(0.6), fontWeight: FontWeight.w400, ), ), ),
Screen2
TweenAnimationBuilder( duration: pageAnimationDuration, tween: Tween(begin: 24.sp, end: 16.sp), builder: (context, value, child) { return Hero( tag: "animateTitle", child: Text( "Animated Text", style: context.displayLarge?.copyWith( color: darkBlue2.withOpacity(0.6), fontWeight: FontWeight.w400, fontSize: value, ), ), ); }, ),
解决方案
问题根源是Hero组件本身会处理导航过渡动画,嵌套TweenAnimationBuilder会导致双重动画冲突,进而出现卡顿和显示异常。正确的做法是利用Hero的flightShuttleBuilder来自定义过渡期间的字号动画。
修改后的代码
Screen1
Hero( tag: "animateTitle", child: Text( "Animated Text", style: context.headlineMedium?.copyWith( color: white.withOpacity(0.6), fontWeight: FontWeight.w400, fontSize: 14.sp, // 明确指定初始字号 ), ), )
Screen2
Hero( tag: "animateTitle", // 自定义过渡期间的Widget动画 flightShuttleBuilder: ( BuildContext flightContext, Animation<double> animation, HeroFlightDirection flightDirection, BuildContext fromHeroContext, BuildContext toHeroContext, ) { // 获取两个页面的文本样式 final Text fromText = (fromHeroContext.widget as Hero).child as Text; final Text toText = (toHeroContext.widget as Hero).child as Text; // 创建字号和颜色的过渡动画 final Animation<double> fontSizeAnim = Tween<double>( begin: fromText.style?.fontSize ?? 14.sp, end: toText.style?.fontSize ?? 18.sp, ).animate(animation); final Animation<Color?> colorAnim = ColorTween( begin: fromText.style?.color, end: toText.style?.color, ).animate(animation); return AnimatedBuilder( animation: animation, builder: (context, child) { return Text( "Animated Text", style: toText.style?.copyWith( fontSize: fontSizeAnim.value, color: colorAnim.value, ), ); }, ); }, child: Text( "Animated Text", style: context.displayLarge?.copyWith( color: darkBlue2.withOpacity(0.6), fontWeight: FontWeight.w400, fontSize: 18.sp, // 明确指定目标字号 ), ), )
关键说明
- 移除TweenAnimationBuilder:避免和Hero的内置过渡动画冲突,统一由Hero的
flightShuttleBuilder控制过渡效果 - 明确指定字号:不要依赖Theme样式的隐式值,确保动画的起始和目标值准确
- 自定义过渡动画:在
flightShuttleBuilder中通过Tween驱动字号和颜色的平滑变化,保证动画流畅性 - 保持内容一致:两个页面的Hero标签和文本内容必须完全相同,否则Hero动画会失效
内容的提问来源于stack exchange,提问作者Keremovsky
相关产品推荐
相关产品推荐

