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

如何用AnimatedSwitcher和SlideTransition实现Widget左右滑切效果

Flutter 组件左入右出切换动画实现方案

直接用Flutter内置的AnimatedSwitcher就能实现这个效果,不需要引入第三方依赖,大部分人实现失败都是因为没给子组件加唯一标识、没单独区分进入/退出组件的动画方向。

核心实现要点

  • 给AnimatedSwitcher传入的每一个待切换子组件,必须设置全局唯一的Key,否则框架无法识别组件差异,不会触发切换动画,通常用ValueKey绑定组件对应的业务数据即可。
  • 重写transitionBuilder属性,分别判断当前渲染的是进入的新组件还是退出的旧组件,给二者设置反向的水平位移动画:新组件初始位置在屏幕左侧外,动画过程中移动到正常位置;旧组件初始位置在正常位置,动画过程中移动到屏幕右侧外。
  • 可以搭配透明度动画弱化滑动的生硬感,不需要的话直接去掉FadeTransition即可。

可直接复用的代码示例

import 'package:flutter/material.dart';

class SlideSwitchContainer extends StatefulWidget {
  const SlideSwitchContainer({super.key});

  @override
  State<SlideSwitchContainer> createState() => _SlideSwitchContainerState();
}

class _SlideSwitchContainerState extends State<SlideSwitchContainer> {
  // 切换标识,实际开发替换成你的业务状态即可
  int _activeIndex = 0;
  // 待切换的组件列表
  final List<Widget> _switchWidgets = const [
    Center(child: Text('组件A', style: TextStyle(fontSize: 28))),
    Center(child: Text('组件B', style: TextStyle(fontSize: 28))),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            SizedBox(
              width: double.infinity,
              height: 320,
              child: AnimatedSwitcher(
                // 动画时长可根据需求调整
                duration: const Duration(milliseconds: 280),
                // 切换动画构造逻辑
                transitionBuilder: (child, baseAnimation) {
                  // 区分进入/退出组件
                  final isNewWidget = child.key == ValueKey(_activeIndex);
                  // 新组件从左滑入,旧组件向右滑出
                  final slideTween = isNewWidget
                      ? Tween<Offset>(begin: const Offset(-1, 0), end: Offset.zero)
                      : Tween<Offset>(begin: Offset.zero, end: const Offset(1, 0));

                  return SlideTransition(
                    position: slideTween.animate(CurvedAnimation(
                      parent: baseAnimation,
                      curve: Curves.easeOutCubic,
                    )),
                    // 不需要淡入淡出效果可以删掉下面的FadeTransition
                    child: FadeTransition(
                      opacity: baseAnimation,
                      child: child,
                    ),
                  );
                },
                // 给子组件绑定唯一Key
                child: KeyedSubtree(
                  key: ValueKey(_activeIndex),
                  child: _switchWidgets[_activeIndex],
                ),
              ),
            ),
            const SizedBox(height: 48),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _activeIndex = _activeIndex == 0 ? 1 : 0;
                });
              },
              child: const Text('触发切换'),
            )
          ],
        ),
      ),
    );
  }
}

扩展说明

  • 如果需要支持反向切换(比如返回场景下新组件从右侧滑入、旧组件向左滑出),只要加一个方向参数控制Tween的偏移量正负即可,不需要重写核心逻辑。
  • 不要手动用Stack叠加两个组件分别控制动画,性能远低于内置的AnimatedSwitcher,而且退出组件的销毁时机很难控制,容易出现内存占用过高的问题。
  • 动画曲线、时长都可以根据设计稿调整,示例里的参数是最接近原生系统组件切换手感的配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:31:18