如何使用flutter_animate包实现滚动时多子组件动画效果
实现滚动组件可见时的动画效果
核心思路:封装通用可见性动画组件
把可见性检测和动画逻辑封装成一个可复用组件,让每个需要动画的Text、Image等组件只需套一层即可,无需重复编写冗余代码。这里结合visibility_detector和flutter_animate实现,兼顾简洁性与灵活性。
步骤1:添加依赖
在pubspec.yaml中引入所需库:
dependencies: flutter: sdk: flutter visibility_detector: ^0.4.0+2 flutter_animate: ^4.5.0
步骤2:封装通用动画组件
import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:visibility_detector/visibility_detector.dart'; class AnimateOnVisible extends StatefulWidget { final Widget child; final List<Effect> effects; final double visibilityThreshold; const AnimateOnVisible({ super.key, required this.child, required this.effects, this.visibilityThreshold = 0.5, }); @override State<AnimateOnVisible> createState() => _AnimateOnVisibleState(); } class _AnimateOnVisibleState extends State<AnimateOnVisible> { bool _isVisible = false; @override Widget build(BuildContext context) { return VisibilityDetector( key: Key('${widget.child.hashCode}-visibility'), onVisibilityChanged: (info) { if (info.visibleFraction >= widget.visibilityThreshold && !_isVisible) { setState(() => _isVisible = true); } }, child: widget.child.animate( autoPlay: _isVisible, effects: widget.effects, ), ); } }
步骤3:在SingleChildScrollView中使用
SingleChildScrollView( child: Column( children: [ // Text组件入场动画 AnimateOnVisible( effects: [ FadeEffect(duration: 800.ms), SlideEffect(begin: const Offset(0, 20), duration: 800.ms), ], child: const Text( '这是一段可见时淡入的文本', style: TextStyle(fontSize: 20), ), ), const SizedBox(height: 1000), // 制造滚动空间 // Image组件入场动画 AnimateOnVisible( effects: [ ScaleEffect(begin: const Offset(0.8, 0.8), duration: 600.ms), FadeEffect(duration: 600.ms), ], child: Image.asset('assets/images/example.png'), ), // 更多组件直接嵌套AnimateOnVisible即可 ], ), )
flutter_animate与ScrollController适配说明(翻译自官方文档)
flutter_animate的适配器与控制器功能说明:
- 适配器可让动画与外部控制器(如ScrollController、PageController)联动,实现基于滚动位置的动态动画效果。
- 例如
ScrollAdapter绑定ScrollController后,能根据滚动偏移量驱动动画进度,示例代码:ListView( controller: scrollController, children: [ Text('随滚动变化的文本').animate( adapter: ScrollAdapter(controller: scrollController), effects: [ FadeEffect(curve: Curves.easeInOut), ScaleEffect(begin: 0.5), ], ), ], ) - 这种方式适合需要随滚动过程持续变化的动画,而前面的可见性触发动画是一次性入场效果,可根据需求选择使用。
方案优势
- 通用组件封装后,多组件场景下代码量极少,只需简单嵌套。
- 基于visibility_detector的可见性检测精准,支持自定义触发阈值(如组件50%可见时启动动画)。
- 借助flutter_animate的丰富预设动画,无需手动编写AnimationController,快速实现各种入场效果。
内容的提问来源于stack exchange,提问作者Omar Ramadan
相关产品推荐
相关产品推荐

