You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

页面导航时实现文本字体大小平滑过渡的问题

问题描述
  • 需求:页面导航时实现文本字体大小的平滑过渡,例如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, // 明确指定目标字号
    ),
  ),
)

关键说明

  1. 移除TweenAnimationBuilder:避免和Hero的内置过渡动画冲突,统一由Hero的flightShuttleBuilder控制过渡效果
  2. 明确指定字号:不要依赖Theme样式的隐式值,确保动画的起始和目标值准确
  3. 自定义过渡动画:在flightShuttleBuilder中通过Tween驱动字号和颜色的平滑变化,保证动画流畅性
  4. 保持内容一致:两个页面的Hero标签和文本内容必须完全相同,否则Hero动画会失效

内容的提问来源于stack exchange,提问作者Keremovsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 02:35:26