Flutter 动画的实现方法汇总

180 阅读2分钟

实现 Flutter 动画的方法有很多,Flutter 提供了强大的动画框架,以下是常见的几种实现方法:

1. 基于 TweenAnimationController

这种方法最常用,适合需要自定义动画的场景。

步骤:

  1. 创建一个 AnimationController
  2. 创建一个 Tween,并将其与 AnimationController 绑定。
  3. AnimationControlleraddListener 方法中调用 setState 以重绘 Widget。

示例代码:

class MyAnimationWidget extends StatefulWidget {
  @override
  _MyAnimationWidgetState createState() => _MyAnimationWidgetState();
}

class _MyAnimationWidgetState extends State<MyAnimationWidget> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );
    _animation = Tween<double>(begin: 0, end: 300).animate(_controller)
      ..addListener(() {
        setState(() {});
      });
    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Container(
      width: _animation.value,
      height: _animation.value,
      color: Colors.blue,
    );
  }
}

2. 使用 AnimatedWidget

AnimatedWidget 封装了 addListenersetState,使得代码更简洁。

示例代码:

class MyAnimatedWidget extends AnimatedWidget {
  MyAnimatedWidget({Key key, Animation<double> animation})
      : super(key: key, listenable: animation);

  @override
  Widget build(BuildContext context) {
    final Animation<double> animation = listenable;
    return Container(
      width: animation.value,
      height: animation.value,
      color: Colors.blue,
    );
  }
}

class MyAnimationWidget extends StatefulWidget {
  @override
  _MyAnimationWidgetState createState() => _MyAnimationWidgetState();
}

class _MyAnimationWidgetState extends State<MyAnimationWidget> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );
    _animation = Tween<double>(begin: 0, end: 300).animate(_controller);
    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return MyAnimatedWidget(animation: _animation);
  }
}

3. 使用 AnimatedBuilder

AnimatedBuilder 进一步简化了动画的实现,它将动画和 Widget 的构建逻辑分离。

示例代码:

class MyAnimationWidget extends StatefulWidget {
  @override
  _MyAnimationWidgetState createState() => _MyAnimationWidgetState();
}

class _MyAnimationWidgetState extends State<MyAnimationWidget> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );
    _animation = Tween<double>(begin: 0, end: 300).animate(_controller);
    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        return Container(
          width: _animation.value,
          height: _animation.value,
          color: Colors.blue,
        );
      },
    );
  }
}

4. 使用内置的 AnimatedContainer

AnimatedContainer 是一个方便的动画实现方法,适合简单的动画需求。

示例代码:

class MyAnimatedContainer extends StatefulWidget {
  @override
  _MyAnimatedContainerState createState() => _MyAnimatedContainerState();
}

class _MyAnimatedContainerState extends State<MyAnimatedContainer> {
  double _width = 50;
  double _height = 50;

  void _animateContainer() {
    setState(() {
      _width = _width == 50 ? 200 : 50;
      _height = _height == 50 ? 200 : 50;
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _animateContainer,
      child: AnimatedContainer(
        width: _width,
        height: _height,
        color: Colors.blue,
        duration: Duration(seconds: 1),
        curve: Curves.easeInOut,
      ),
    );
  }
}

5. 使用 Hero 动画

Hero 动画适用于页面跳转时的共享元素动画。

示例代码:

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First Page')),
      body: Center(
        child: GestureDetector(
          onTap: () {
            Navigator.push(context, MaterialPageRoute(builder: (context) => SecondPage()));
          },
          child: Hero(
            tag: 'hero-tag',
            child: Container(
              width: 100,
              height: 100,
              color: Colors.blue,
            ),
          ),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Center(
        child: Hero(
          tag: 'hero-tag',
          child: Container(
            width: 200,
            height: 200,
            color: Colors.blue,
          ),
        ),
      ),
    );
  }
}

总结

上述方法涵盖了 Flutter 动画实现的主要方式,具体选择哪种方法取决于具体的需求和复杂度。希望这些示例能帮助你更好地理解和实现 Flutter 动画。