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

如何自定义Flutter的CupertinoPageRoute返回动画方向?

自定义Flutter Cupertino导航返回动画(右滑入效果)

要实现返回操作时页面从右侧滑入的效果,无需重新推送Page1,可通过以下两种方式实现:

方法一:继承CupertinoPageRoute重写过渡动画

直接修改CupertinoPageRoute的pop阶段过渡逻辑,保持push动画默认,替换pop动画方向:

class ReversePopCupertinoRoute<T> extends CupertinoPageRoute<T> {
  ReversePopCupertinoRoute({
    required WidgetBuilder builder,
    RouteSettings? settings,
    bool maintainState = true,
    bool fullscreenDialog = false,
  }) : super(
          builder: builder,
          settings: settings,
          maintainState: maintainState,
          fullscreenDialog: fullscreenDialog,
        );

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    // Push时保持默认的右滑入动画
    if (animation.status == AnimationStatus.forward) {
      return super.buildTransitions(context, animation, secondaryAnimation, child);
    } 
    // Pop时修改动画:当前页面左滑出,上一页从右滑入
    else {
      return CupertinoPageTransition(
        primaryRouteAnimation: animation,
        secondaryRouteAnimation: ReverseAnimation(animation),
        linearTransition: linearTransition,
        child: child,
      );
    }
  }
}

使用方式

跳转Page2时使用自定义路由:

Navigator.push(
  context,
  ReversePopCupertinoRoute(builder: (context) => Page2()),
);

返回Page1时直接调用默认pop:

Navigator.pop(context);

方法二:用PageRouteBuilder自定义完整过渡

通过PageRouteBuilder同时定义push和pop的动画逻辑,更灵活可控:

Route customSlideRoute(Widget page) {
  return PageRouteBuilder(
    transitionDuration: Duration(milliseconds: 300), // 对齐Cupertino默认时长
    pageBuilder: (context, animation, secondaryAnimation) => page,
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      // Push动画:新页面从右到左滑入
      final pushTween = Tween<Offset>(
        begin: Offset(1.0, 0.0),
        end: Offset.zero,
      ).animate(CurvedAnimation(parent: animation, curve: Curves.easeInOut));

      // Pop动画:当前页面左滑出,上一页右滑入
      final popOutTween = Tween<Offset>(
        begin: Offset.zero,
        end: Offset(-1.0, 0.0),
      ).animate(CurvedAnimation(parent: secondaryAnimation, curve: Curves.easeInOut));
      
      final popInTween = Tween<Offset>(
        begin: Offset(1.0, 0.0),
        end: Offset.zero,
      ).animate(CurvedAnimation(parent: secondaryAnimation, curve: Curves.easeInOut));

      return Stack(
        children: [
          // 上一页的pop入场动画
          SlideTransition(
            position: popInTween,
            child: ModalRoute.of(context)?.previousContentWidget ?? SizedBox.shrink(),
          ),
          // 当前页面的push/pop动画
          SlideTransition(
            position: animation.status == AnimationStatus.forward ? pushTween : popOutTween,
            child: child,
          ),
        ],
      );
    },
  );
}

使用方式

跳转和返回逻辑与方法一完全一致:

// 跳转Page2
Navigator.push(context, customSlideRoute(Page2()));
// 返回Page1
Navigator.pop(context);

两种方案都无需重新推送Page1,通过修改路由过渡动画即可实现你要的PageView式切换效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:45:42