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

Flutter PageView滑动时如何实现文本进出动画及设置触发点

实现思路

你已经在使用PageController处理图片滚动逻辑,可以直接复用该控制器的状态驱动文本动画,无需额外引入复杂的监听逻辑。

方案1:文本动画跟随滚动实时联动

适合需要和滑动手势强绑定的丝滑过渡效果:

  1. 首先监听PageController的滚动状态,获取当前滚动进度
    final PageController _pageController = PageController();
    // 存储当前滚动的页面进度,滑到第n页到n+1页之间时,值从n平滑过渡到n+1
    double _currentPage = 0;
    
    @override
    void initState() {
      super.initState();
      _pageController.addListener(() {
        setState(() {
          _currentPage = _pageController.page ?? 0;
        });
      });
    }
    
  2. 针对每个页面的文本组件,通过当前进度和页面索引的差值计算动画参数
    以第index页的文本为例,滑入时从右侧平移+渐显,滑出时向左侧平移+渐隐的实现如下:
    // 计算当前页面对应的动画进度,值范围固定在0~1之间
    final animProgress = (_currentPage - index).clamp(0.0, 1.0);
    
    Opacity(
      // 进度为0时完全显示,进度为1时完全隐藏
      opacity: 1 - animProgress,
      child: Transform.translate(
        // 滑入时从右侧100dp位置移动到原点,滑出时向左侧移动100dp
        offset: Offset(animProgress * 100, 0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: const [
            Text('引导页标题', style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600)),
            SizedBox(height: 12),
            Text('引导页描述内容', style: TextStyle(fontSize: 16, color: Colors.grey)),
          ],
        ),
      ),
    )
    

方案2:页面切换完成后触发固定动画

适合不需要跟随滚动联动,仅在页面完全选中后播放文本入场动画的场景:

  1. 初始化每个页面对应的文本动画控制器
    // 假设引导页总共有3页,每个页面对应一个独立的动画控制器
    late List<AnimationController> _textAnimControllers;
    late List<Animation<Offset>> _slideAnims;
    late List<Animation<double>> _fadeAnims;
    
    @override
    void initState() {
      super.initState();
      _textAnimControllers = List.generate(3, (index) => AnimationController(
        vsync: this,
        duration: const Duration(milliseconds: 500),
      ));
      // 平移动画:从下方30dp位置上移到原点
      _slideAnims = _textAnimControllers.map((controller) => Tween<Offset>(
        begin: const Offset(0, 30),
        end: Offset.zero,
      ).animate(CurvedAnimation(parent: controller, curve: Curves.easeOut))).toList();
      // 渐变动画:从完全透明到完全显示
      _fadeAnims = _textAnimControllers.map((controller) => Tween<double>(
        begin: 0,
        end: 1,
      ).animate(CurvedAnimation(parent: controller, curve: Curves.easeOut))).toList();
    }
    
  2. 绑定PageView的页面切换回调作为动画触发点
    PageView(
      controller: _pageController,
      onPageChanged: (index) {
        // 重置所有页面的动画状态
        for (var controller in _textAnimControllers) {
          controller.reset();
        }
        // 触发当前选中页面的文本入场动画
        _textAnimControllers[index].forward();
      },
      children: [],
    )
    
  3. 给每个页面的文本绑定动画
    // 第index页的文本组件
    FadeTransition(
      opacity: _fadeAnims[index],
      child: SlideTransition(
        position: _slideAnims[index],
        child: 你的文本组件,
      ),
    )
    
  4. 页面销毁时释放所有控制器资源
    @override
    void dispose() {
      _pageController.dispose();
      for (var controller in _textAnimControllers) {
        controller.dispose();
      }
      super.dispose();
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:54:04