常见的显式动画有RotationTransition、FadeTransition、ScaleTransition、SlideTransition、
AnimatedIcon。在显示动画中开发者需要创建一个AnimationController,通过AnimationController
控制动画的开始、暂停、重置、跳转、倒播等。

RotationTransition(旋转动画)、 AnimationController

示例1:AnimationController普通用法
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {   //加 with SingleTickerProviderStateMixin
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    _controller = AnimationController(
      vsync: this,  //程序的刷新频率与手机的频率统一
//Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂
// 直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保
// 持同步,以达到供需平衡的效果,防止卡顿现象。
      duration: const Duration(seconds: 5), //程序的执行时间
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          RotationTransition(
            turns: _controller, //调用
            child: const FlutterLogo(  //Logo
              size: 150,
            ),
          ),
          const SizedBox(
            height: 40,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
            child: Wrap(
              spacing: 10,
              alignment: WrapAlignment.center,
              children: [
                ElevatedButton(
                    onPressed: () {
                      _controller.forward(); //正序播放一次
                    },
                    child: const Text("Forward")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reverse(); //倒序播放一次
                    },
                    child: const Text("Reverse")),
                ElevatedButton(
                    onPressed: () {
                      _controller.stop(); //停止播放
                    },
                    child: const Text("Stop")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reset(); //重置
                    },
                    child: const Text("rest")),
                ElevatedButton(
                    onPressed: () {
                      _controller.repeat(); //重复播放
                    },
                    child: const Text("repeat"))
              ],
            ),
          )
        ],
      ),
    );
  }
}
示例2:lowerBound upperBound
AnimationController 用于控制动画,它包含动画的启动 forward() 、停止 stop() 、反向播放
reverse() 等方法。 AnimationController 会在动画的每一帧,就会生成一个新的值。默认情况
下, AnimationController 在给定的时间段内线性的生成从 0.0 到1.0(默认区间)的数字 ,我们也
可以通过 lowerbound 和 upperBound 来修改 AnimationController 生成数字的区间。
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    _controller = AnimationController(
        vsync: this,
//Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂
// 直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保
// 持同步,以达到供需平衡的效果,防止卡顿现象。
        duration: const Duration(seconds: 1),
        lowerBound: 3, //第三圈转到第五圈
        upperBound: 5);
    _controller.addListener(() {
      print(_controller.value);
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          RotationTransition(
            turns: _controller,
            child: const FlutterLogo(
              size: 100,
            ),
          ),
          const SizedBox(
            height: 40,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
            child: Wrap(
              spacing: 10,
              alignment: WrapAlignment.center,
              children: [
                ElevatedButton(
                    onPressed: () {
                      _controller.forward(); //正序播放一次
                    },
                    child: const Text("Forward")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reverse(); //倒序播放一次
                    },
                    child: const Text("Reverse")),
                ElevatedButton(
                    onPressed: () {
                      _controller.stop(); //停止播放
                    },
                    child: const Text("Stop")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reset(); //重置
                    },
                    child: const Text("rest")),
                ElevatedButton(
                    onPressed: () {
                      _controller.repeat(); //重复播放
                    },
                    child: const Text("repeat"))
              ],
            ),
          )
        ],
      ),
    );
  }
}

FadeTransition(透明到显示)

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    _controller = AnimationController(
      vsync: this,
//Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂
// 直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保
// 持同步,以达到供需平衡的效果,防止卡顿现象。
      duration: const Duration(seconds: 1),
        lowerBound: 0.5, //第三圈转到第五圈
        upperBound: 1
    );
  }

  @override
  void dispose() {
// TODO: implement dispose
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          FadeTransition(
            opacity: _controller,
            child: const FlutterLogo(size: 80),
          ),
          const SizedBox(
            height: 40,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                    onPressed: () {
                      _controller.forward(); //正序播放一次
                    },
                    child: const Text("Forward")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reverse(); //倒序播放一次
                    },
                    child: const Text("Reverse")),
              ],
            ),
          )
        ],
      ),
    );
  }
}

ScaleTransition(动画放大与缩小)、Tween

示例1:AnimationController控制动画:
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    _controller = AnimationController(
      vsync: this, //Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂
// 直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保
// 持同步,以达到供需平衡的效果,防止卡顿现象。
      duration: const Duration(seconds: 1),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          ScaleTransition(
            scale: _controller,
            child: const FlutterLogo(size: 80),
          ),
          const SizedBox(
            height: 40,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                    onPressed: () {
                      _controller.forward(); //正序播放一次
                    },
                    child: const Text("Forward")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reverse(); //倒序播放一次
                    },
                    child: const Text("Reverse")),
              ],
            ),
          )
        ],
      ),
    );
  }
}
示例2: AnimationController结合Tween控制动画:
默认情况下, AnimationController 对象值的范围是[0.0,1.0]。如果我们需要构建UI的动画值在不同
的范围或不同的数据类型,则可以使用 Tween 来添加映射以生成不同的范围或数据类型的值
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    _controller = AnimationController(
      vsync: this, //Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂
// 直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保
// 持同步,以达到供需平衡的效果,防止卡顿现象。
      duration: const Duration(seconds: 1),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          ScaleTransition(
            scale: _controller.drive(Tween(begin: 1, end: 2)), //动画开始与结束的大小
            child: const FlutterLogo(size: 80),
          ),
          const SizedBox(
            height: 40,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                    onPressed: () {
                      _controller.forward(); //正序播放一次
                    },
                    child: const Text("Forward")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reverse(); //倒序播放一次
                    },
                    child: const Text("Reverse")),
              ],
            ),
          )
        ],
      ),
    );
  }
}

SlideTransition(位移)

这是一负责平移的显示动画组件,使用时需要通过position属性传入一个Animated表示位移程度,通常
借助Tween实现。
示例1: _controller.drive驱动动画
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    _controller = AnimationController(
      vsync: this,
//Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂
// 直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保
// 持同步,以达到供需平衡的效果,防止卡顿现象。
      duration: const Duration(seconds: 1),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          SlideTransition(
            position: _controller.drive(Tween(
                begin: const Offset(0, 0),
                end: const Offset(1.2, 0) //表示实际的位置向右移动自身宽度的1.2倍
                )),
            child: const FlutterLogo(size: 80),
          ),
          const SizedBox(
            height: 40,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                    onPressed: () {
                      _controller.forward(); //正序播放一次
                    },
                    child: const Text("Forward")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reverse(); //倒序播放一次
                    },
                    child: const Text("Reverse")),
              ],
            ),
          )
        ],
      ),
    );
  }
}
示例2:Tween.animate 驱动动画
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    _controller = AnimationController(
      vsync: this, //Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂
// 直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保
// 持同步,以达到供需平衡的效果,防止卡顿现象。
      duration: const Duration(seconds: 1),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          SlideTransition(
            position: Tween(
                    begin: const Offset(0, 0),
                    end: const Offset(1.2, 0) //表示实际的位置向右移动自身宽度的1.2倍
                    )
                .animate(_controller),
            child: const FlutterLogo(size: 80),
          ),
          const SizedBox(
            height: 40,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                    onPressed: () {
                      _controller.forward(); //正序播放一次
                    },
                    child: const Text("Forward")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reverse(); //倒序播放一次
                    },
                    child: const Text("Reverse")),
              ],
            ),
          )
        ],
      ),
    );
  }
}
示例3: 链式操作修改动画效果
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    _controller = AnimationController(
      vsync: this, //Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂
// 直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保
// 持同步,以达到供需平衡的效果,防止卡顿现象。
      duration: const Duration(seconds: 1),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          SlideTransition(
            position: Tween(
                    begin: const Offset(0, -1),
                    end: const Offset(0, 0.8) //表示实际的位置向右移动自身宽度的1.2倍
                    )
                .chain(CurveTween(curve: Curves.bounceIn)) //运动的曲线即运动的效果
                .animate(_controller),
            child: const FlutterLogo(size: 80),
          ),
          const SizedBox(
            height: 40,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                    onPressed: () {
                      _controller.forward(); //正序播放一次
                    },
                    child: const Text("Forward")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reverse(); //倒序播放一次
                    },
                    child: const Text("Reverse")),
              ],
            ),
          )
        ],
      ),
    );
  }
}
示例4: 链式操作修改动动画执行时间(交错式动画)
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    _controller = AnimationController(
      vsync: this, //Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂
// 直同步信号,只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保
// 持同步,以达到供需平衡的效果,防止卡顿现象。
      duration: const Duration(seconds: 3),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          SlideTransition(
            position: Tween(
                    begin: const Offset(0, -1),
                    end: const Offset(0, 0.6) //表示实际的位置向右移动自身宽度的1.2倍
                    )
                .chain(CurveTween(curve: Curves.bounceIn))
                .chain(CurveTween(curve: const Interval(0.6, 0.8)))//最后的百分之20的时间完成动画

                .animate(_controller),
            child: const FlutterLogo(size: 80),
          ),
          const SizedBox(
            height: 40,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                    onPressed: () {
                      _controller.forward(); //正序播放一次
                    },
                    child: const Text("Forward")),
                ElevatedButton(
                    onPressed: () {
                      _controller.reverse(); //倒序播放一次
                    },
                    child: const Text("Reverse")),
              ],
            ),
          )
        ],
      ),
    );
  }
}

AnimatedIcon

AnimatedIcon顾名思义,是一个用于提供动画图标的组件,它的名字虽然是以Animated开头,但是他
是一个显式动画组件,需要通过progress属性传入动画控制器,另外需要由Icon属性传入动画图标数据
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() {
// TODO: implement initState
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 1)); //过度的时间为一秒
  }

  @override
  void dispose() {
// TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () {
          _controller.forward();
        },
      ),
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Center(
        child: AnimatedIcon(
            icon: AnimatedIcons.menu_close, progress: _controller, size: 40), //这是menu到close的过度
      ),
    );
  }
}

 

 
posted on 2024-03-04 22:19  鲤斌  阅读(92)  评论(0编辑  收藏  举报