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

Flutter中切换home内容时如何添加页面切换动画?

实现固定顶部栏+页面侧滑切换动画的Flutter方案

方案一:嵌套Navigator(贴合原生Navigator侧滑体验)

这种方式能完美保留顶部固定栏,同时让下方内容拥有和原生Navigator一致的侧滑切换动画,核心是在顶部栏下方嵌套一个独立的Navigator来管理页面栈。

修改后的代码示例:

class Segunda extends StatefulWidget {
  @override
  _SegundaState createState() => _SegundaState(); // 修正State命名规范
}

class _SegundaState extends State<Segunda> {
  late Size size;
  late double heightA, widthA;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    size = MediaQuery.of(context).size;
    heightA = size.height;
    widthA = size.width;
    // 避免在build中调用setState引发无限重绘,将尺寸计算移至此处
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          // 固定顶部蓝色栏
          SizedBox(
            width: widthA,
            height: heightA * 0.1,
            child: Container(
              color: Colors.blue,
              child: ElevatedButton(
                onPressed: () {
                  // 通过嵌套Navigator触发侧滑跳转动画
                  Navigator.of(_navigatorKey.currentContext!).push(
                    MaterialPageRoute(
                      builder: (context) => Segunda3(),
                    ),
                  );
                },
                child: const Text("Change"),
              ),
            ),
          ),
          // 嵌套Navigator管理下方页面
          SizedBox(
            width: widthA,
            height: heightA * 0.9,
            child: Navigator(
              key: _navigatorKey,
              initialRoute: '/',
              onGenerateRoute: (settings) {
                if (settings.name == '/') {
                  return MaterialPageRoute(builder: (_) => Segunda2());
                }
                return MaterialPageRoute(builder: (_) => Segunda3());
              },
            ),
          ),
        ],
      ),
    );
  }

  final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
}

关键说明:

  • 替换原代码中的MaterialApp为嵌套Navigator,通过GlobalKey获取嵌套Navigator上下文,方便外部按钮触发跳转
  • 顶部栏作为父布局的固定部分,不会被嵌套Navigator的页面替换
  • 使用MaterialPageRoute自带原生侧滑入栈动画,也可改用CupertinoPageRoute实现iOS风格侧滑

方案二:PageView(适合简单页面切换)

如果页面数量不多、不需要完整路由栈管理,用PageView可快速实现左右滑动切换,同时支持按钮手动控制切换动画。

代码示例:

class Segunda extends StatefulWidget {
  @override
  _SegundaState createState() => _SegundaState();
}

class _SegundaState extends State<Segunda> {
  late Size size;
  late double heightA, widthA;
  final PageController _pageController = PageController(initialPage: 0);
  int _currentPage = 0;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    size = MediaQuery.of(context).size;
    heightA = size.height;
    widthA = size.width;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          SizedBox(
            width: widthA,
            height: heightA * 0.1,
            child: Container(
              color: Colors.blue,
              child: ElevatedButton(
                onPressed: () {
                  if (_currentPage < 1) { // 假设仅两个页面
                    _pageController.nextPage(
                      duration: const Duration(milliseconds: 300),
                      curve: Curves.easeInOut,
                    );
                  }
                },
                child: const Text("Change"),
              ),
            ),
          ),
          SizedBox(
            width: widthA,
            height: heightA * 0.9,
            child: PageView(
              controller: _pageController,
              onPageChanged: (index) {
                setState(() => _currentPage = index);
              },
              children: const [
                Segunda2(),
                Segunda3(),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

关键说明:

  • PageView自带左右滑动手势,也可通过PageController的nextPage/previousPage方法手动触发切换动画
  • 适合页面数量少、无需路由栈(如返回上一页)的场景

方案三:AnimatedSwitcher+SlideTransition(自定义动画)

如果需要完全自定义切换动画(如调整滑动方向、速度),可使用AnimatedSwitcher配合SlideTransition实现:

代码示例:

class Segunda extends StatefulWidget {
  @override
  _SegundaState createState() => _SegundaState();
}

class _SegundaState extends State<Segunda> {
  late Size size;
  late double heightA, widthA;
  int _currentIndex = 0;
  final List<Widget> _pages = const [Segunda2(), Segunda3()];

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    size = MediaQuery.of(context).size;
    heightA = size.height;
    widthA = size.width;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          SizedBox(
            width: widthA,
            height: heightA * 0.1,
            child: Container(
              color: Colors.blue,
              child: ElevatedButton(
                onPressed: () {
                  setState(() {
                    _currentIndex = (_currentIndex + 1) % _pages.length;
                  });
                },
                child: const Text("Change"),
              ),
            ),
          ),
          SizedBox(
            width: widthA,
            height: heightA * 0.9,
            child: AnimatedSwitcher(
              duration: const Duration(milliseconds: 300),
              transitionBuilder: (child, animation) {
                // 自定义从左侧滑入的动画
                return SlideTransition(
                  position: Tween<Offset>(
                    begin: const Offset(-1.0, 0.0),
                    end: Offset.zero,
                  ).animate(animation),
                  child: child,
                );
              },
              child: _pages[_currentIndex],
              key: ValueKey<int>(_currentIndex), // 必须给子项唯一key才能触发动画
            ),
          ),
        ],
      ),
    );
  }
}

关键说明:

  • 必须为每个子Widget设置唯一ValueKey,AnimatedSwitcher才能识别页面变化并触发动画
  • 修改Tween<Offset>的begin值可自定义动画方向(如从右侧滑入改为Offset(1.0, 0.0))

原代码小问题修正

  1. State类命名不符合规范,应改为_SegundaState(私有类),避免与其他组件混淆
  2. 不要在build方法中调用setState,会引发无限重绘循环,屏幕尺寸计算应移至didChangeDependencies中

内容的提问来源于stack exchange,提问作者Anxo Gómez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:21:02