通过几行代码就可以实现隐式动画,由于隐式动画背后的实现原理和繁琐的操作细节都被隐去了,所以
叫隐式动画,FLutter中提供的 AnimatedContainer、AnimatedPadding、AnimatedPositioned、
AnimatedOpacity、AnimatedDefaultTextStyle、AnimatedSwitcher都属于隐式动画。
隐式动画中可以通过 duration 配置动画时长、可以通过 Curve (曲线)来配置动画过程
AnimatedContainer
class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { bool flag = true; @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( child: const Icon(Icons.animation), onPressed: () { setState(() { flag = !flag; }); }, ), appBar: AppBar( title: const Text("AnimatedContainer Demo"), ), body: Center( child: AnimatedContainer( duration: const Duration(milliseconds: 500), // 动画时长500 ms width: flag ? 100 : 200, height: flag ? 100 : 200, color: Colors.blue, transform: flag ? Matrix4.translationValues(130, 0, 0) : Matrix4.translationValues(0, 0, 130), //位移 ), ), ); } }
从侧边滑动
class Mypage extends StatefulWidget { const Mypage({super.key}); @override State<Mypage> createState() => _MypageState(); } class _MypageState extends State<Mypage> { bool flag = true; @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( child: const Icon(Icons.animation), onPressed: () { setState(() { print("点击了"); flag = !flag; }); }, ), appBar: AppBar( title: const Text("我是一个标题"), ), body: Stack( children: [ ListView( children: const [ ListTile( title: Text("我的一个列表"), ) ], ), Positioned( left: 0, top: 0, bottom: 0, child: AnimatedContainer( duration: const Duration(milliseconds: 500), // 动画时长500 ms width: 200, height: double.infinity, color: Colors.blue, transform: flag ? Matrix4.translationValues(-200, 0, 0) : Matrix4.translationValues(0, 0, 0), //位移 ), ) ], )); } }
AnimatedPadding以及curve属性
Curves曲线值:
class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { bool flag = true; @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( child: const Icon(Icons.animation), onPressed: () { setState(() { flag = !flag; }); }, ), body: AnimatedPadding( duration: const Duration(milliseconds: 1000), // 动画时长500 ms curve: Curves.linear, //Curves曲线值 padding: EdgeInsets.fromLTRB(10, flag ? 10 : 500, 0, 0), child: Container( width: 100, height: 100, color: Colors.red, ), ), ); } }
AnimatedPositioned
class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { bool flag = true; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("AnimatedPositioned Demo"), ), body: Stack( children: [ AnimatedPositioned( curve: Curves.easeInOut, duration: const Duration(seconds: 1), top: flag ? 10 : 500, left: flag ? 10 : 300, child: Container( width: 60, height: 60, color: Colors.blue, ), ), Align( alignment: const Alignment(0, 0.8), child: ElevatedButton( child: const Text("Transform"), onPressed: () { setState(() { flag = !flag; }); }, ), ), ], ), ); } }
AnimatedOpacity
class _MyHomePageState extends State<MyHomePage> { bool flag = true; @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { setState(() { flag = !flag; }); }, child: const Icon(Icons.opacity), ), appBar: AppBar( title: const Text("AnimatedPositioned Demo"), ), body: Center( child: AnimatedOpacity( curve: Curves.linear, duration: const Duration(seconds: 1), //时间 opacity: flag ? 1 : 0.3, //透明度 child: Container( width: 300, height: 300, color: Colors.blue, ), ), ), ); } }
AnimatedDefaultTextStyle
class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { bool flag = true; @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { setState(() { flag = !flag; }); }, child: const Icon(Icons.opacity), ), appBar: AppBar( title: const Text("AnimatedPositioned Demo"), ), body: Center( child: Container( alignment: Alignment.center, width: 300, height: 300, color: Colors.blue, child: AnimatedDefaultTextStyle( duration: const Duration(seconds: 1), style: TextStyle( fontSize: flag ? 20 : 50, ), child: const Text("你好Flutte"), ), ), ), ); } }
AnimatedSwitcher 以及transitionBuilder
上面的AnimatedContainer、AnimatedPadding、AnimatedPositioned、AnimatedOpacity、
AnimatedDefaultTextStyle都是在属性改变的时候执行动画,AnimatedSwitcher则是在子元素改变的
时候执行动画。
相比上面的动画组件AnimatedSwitcher多了transitionBuilder参数,可以在transitionBuilder中自定义
动画
示例1:载页面前显示一个loading动画,加载完毕后显示对于的内容
class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { bool flag = true; @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { setState(() { flag = !flag; }); }, child: const Icon(Icons.opacity), ), appBar: AppBar( title: const Text("AnimatedPositioned Demo"), ), body: Center( child: Container( alignment: Alignment.center, width: 300, height: 180, color: Colors.yellow, child: AnimatedSwitcher( //子元素的动画 duration: const Duration(milliseconds: 1000), child: flag ? const CircularProgressIndicator() //圈圈 : Image.network( "https://www.itying.com/images/flutter/2.png", fit: BoxFit.contain, ), ), ), ), ); } }
示例2:通过transitionBuilder自定义动画效果
class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { bool flag = true; @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { setState(() { flag = !flag; }); }, child: const Icon(Icons.opacity), ), appBar: AppBar( title: const Text("AnimatedPositioned Demo"), ), body: Center( child: Container( alignment: Alignment.center, width: 300, height: 180, color: Colors.yellow, child: AnimatedSwitcher( transitionBuilder: ((child, animation) { //自定义动画效果 return ScaleTransition( scale: animation, child: FadeTransition( //用这个动画加载下面的 opacity: animation, child: child, //可以多个动画叠加在一起 ), ); }), duration: const Duration(milliseconds: 400), child: flag ? const CircularProgressIndicator() : Image.network( "https://www.itying.com/images/flutter/2.png", fit: BoxFit.contain, ), ), ), ), ); } }
示例3:通过transitionBuilder改变子元素执行动画
class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { bool flag = true; @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { setState(() { flag = !flag; }); }, child: const Icon(Icons.opacity), ), appBar: AppBar( title: const Text("AnimatedPositioned Demo"), ), body: Center( child: Container( alignment: Alignment.center, width: 300, height: 180, color: Colors.yellow, child: AnimatedSwitcher( transitionBuilder: ((child, animation) { return ScaleTransition( scale: animation, child: FadeTransition( opacity: animation, child: child, ), ); }), duration: const Duration(milliseconds: 400), child: Text( key: UniqueKey(), //让文字执行动画 flag ? "你好Flutter" : "你好大地", style: const TextStyle(fontSize: 30), ), ), ), ), ); } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)