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

如何在Flutter中创建动画PageView及曲线页面动画效果?

Flutter 动画 PageView 及曲线页面动画实现

一、基础动画 PageView 实现

普通的动画 PageView 可以通过结合 PageController 和动画控制器实现页面切换过渡,或是用自带组件实现丰富切换效果,以下是两种常用方式:

方式1:PageController 配合动画控制页面切换

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

  @override
  State<AnimatedPageView> createState() => _AnimatedPageViewState();
}

class _AnimatedPageViewState extends State<AnimatedPageView> with SingleTickerProviderStateMixin {
  late PageController _pageController;
  late AnimationController _animationController;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _pageController = PageController(initialPage: 0);
    _animationController = AnimationController(
      duration: const Duration(milliseconds: 300),
      vsync: this,
    );
    _animation = CurvedAnimation(parent: _animationController, curve: Curves.easeInOut);
  }

  void _switchPage(int page) {
    _animationController.reset();
    _animationController.forward();
    _pageController.animateToPage(
      page,
      duration: const Duration(milliseconds: 300),
      curve: Curves.easeInOut,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        controller: _pageController,
        children: const [
          Center(child: Text("页面1")),
          Center(child: Text("页面2")),
          Center(child: Text("页面3")),
        ],
      ),
      bottomNavigationBar: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          ElevatedButton(onPressed: () => _switchPage(0), child: const Text("去页面1")),
          ElevatedButton(onPressed: () => _switchPage(1), child: const Text("去页面2")),
          ElevatedButton(onPressed: () => _switchPage(2), child: const Text("去页面3")),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _pageController.dispose();
    _animationController.dispose();
    super.dispose();
  }
}

方式2:PageTransitionSwitcher 搭配 PageView

如果需要淡入淡出、缩放等更丰富的切换动画,可用 PageTransitionSwitcher 包裹页面:

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

  @override
  State<TransitionPageView> createState() => _TransitionPageViewState();
}

class _TransitionPageViewState extends State<TransitionPageView> {
  int _currentPage = 0;
  final PageController _pageController = PageController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageTransitionSwitcher(
        duration: const Duration(milliseconds: 500),
        transitionBuilder: (child, animation, secondaryAnimation) {
          return FadeTransition(
            opacity: animation,
            child: ScaleTransition(
              scale: animation,
              child: child,
            ),
          );
        },
        child: PageView(
          controller: _pageController,
          onPageChanged: (index) => setState(() => _currentPage = index),
          children: List.generate(3, (index) => Center(child: Text("页面${index+1}", key: ValueKey(index)))),
        ),
      ),
    );
  }
}

二、曲线页面动画效果的 PageView 实现

你提供的参考效果(如下方图片所示)是页面切换时带弧度变形的曲线动画,核心是根据页面偏移量计算变换参数,结合 Transform 和 AnimatedBuilder 实现:

曲线页面动画PageView效果

以下是实现代码:

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

  @override
  State<CurvedPageView> createState() => _CurvedPageViewState();
}

class _CurvedPageViewState extends State<CurvedPageView> {
  final PageController _pageController = PageController(viewportFraction: 0.8);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView.builder(
        controller: _pageController,
        itemCount: 5,
        itemBuilder: (context, index) {
          return AnimatedBuilder(
            animation: _pageController,
            builder: (context, child) {
              double value = 1.0;
              if (_pageController.position.haveDimensions) {
                // 获取当前页面的偏移比例
                value = _pageController.page! - index;
                value = (1 - (value.abs() * 0.3)).clamp(0.0, 1.0);
              }
              // 用Matrix4实现曲线变形效果
              return Transform(
                transform: Matrix4.identity()
                  ..setEntry(3, 2, 0.001)
                  ..rotateY(value * 0.3)
                  ..scale(value),
                alignment: Alignment.center,
                child: child,
              );
            },
            child: Container(
              margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(16),
                color: Colors.primaries[index % Colors.primaries.length],
              ),
              child: Center(child: Text("页面${index+1}", style: const TextStyle(fontSize: 24, color: Colors.white))),
            ),
          );
        },
      ),
    );
  }
}

关键说明:

  • viewportFraction: 0.8:设置页面宽度占视口的80%,让相邻页面部分显示,强化曲线效果的视觉层次感
  • AnimatedBuilder:监听PageController滚动状态,实时更新页面变换参数
  • Matrix4:通过旋转、缩放和透视变换模拟曲线弯曲效果,可调整rotateY、scale等参数适配需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:55:16