前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter Loading动画系列中最复杂的一个效果

Flutter Loading动画系列中最复杂的一个效果

作者头像
老孟Flutter
发布2021-10-26 15:05:00
1.5K0
发布2021-10-26 15:05:00
举报
文章被收录于专栏:Flutter

Loading动画系列

github地址:https://github.com/LaoMengFlutter/flutter-do

最复杂的效果

我个人认为最复杂的,也是花费时间最长的动画效果

放慢来看,是一个3x3的矩形,从左下角开始,每一斜排依次缩小,再还原的过程,下面就一步步实现,先绘制一个矩形:

代码语言:javascript
复制
class Square extends StatelessWidget {

  final Color color;

  const Square({Key? key,required this.color}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color,
    );
  }
}

绘制3x3的矩形,并给每一个矩形添加 「ScaleTransition」 ,用于后面实现缩放

代码语言:javascript
复制
@override
  Widget build(BuildContext context) {
    return SizedBox.fromSize(
      size: Size.square(widget.size),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              _square(_anim3, 0),
              _square(_anim4, 1),
              _square(_anim5, 2),
            ],
          ),
          Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              _square(_anim2, 3),
              _square(_anim3, 4),
              _square(_anim4, 5),
            ],
          ),
          Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              _square(_anim1, 6),
              _square(_anim2, 7),
              _square(_anim3, 8),
            ],
          ),
        ],
      ),
    );
  }

  Widget _square(Animation<double> animation, int index) {
    return ScaleTransition(
      scale: animation,
      child: SizedBox.fromSize(
          size: Size.square(widget.size / 3.0),
          child: Square(
            color: widget.color,
          )),
    );
  }

重点来了,为什么需要5个 「Animation」 呢?因为共有5个斜排,同一个斜排使用一个Animation,如图:

其中1-5数字代表代码中的 _anim1, _anim2, _anim3, _anim4, _anim5,动画的效果都是依次缩小,再还原的过程,但1-2-3-4-5依次完成,并不是同时完成,代码如下:

代码语言:javascript
复制
_anim1 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.1, 0.6, curve: widget.curve)));

    _anim2 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.2, 0.7, curve: widget.curve)));

    _anim3 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.3, 0.8, curve: widget.curve)));

    _anim4 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.4, 0.9, curve: widget.curve)));

    _anim5 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.5, 1.0, curve: widget.curve)));

难点解决了,下面是完整的代码:

代码语言:javascript
复制
import 'package:flutter/material.dart';

///
/// desc:
///

class SquareGridScaleLoading extends StatefulWidget {
  final double size;
  final Duration duration;
  final Curve curve;
  final Color color;

  const SquareGridScaleLoading(
      {Key? key,
      this.color = Colors.white,
      this.size = 48.0,
      this.duration = const Duration(milliseconds: 1500),
      this.curve = Curves.linear})
      : super(key: key);

  @override
  _SquareGridScaleLoadingState createState() => _SquareGridScaleLoadingState();
}

class _SquareGridScaleLoadingState extends State<SquareGridScaleLoading>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _anim1, _anim2, _anim3, _anim4, _anim5;

  @override
  void initState() {
    _controller = AnimationController(vsync: this, duration: widget.duration)
      ..repeat();

    _anim1 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.1, 0.6, curve: widget.curve)));

    _anim2 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.2, 0.7, curve: widget.curve)));

    _anim3 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.3, 0.8, curve: widget.curve)));

    _anim4 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.4, 0.9, curve: widget.curve)));

    _anim5 = TweenSequence([
      TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 50),
      TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.0), weight: 50),
    ]).animate(CurvedAnimation(
        parent: _controller, curve: Interval(0.5, 1.0, curve: widget.curve)));

    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return SizedBox.fromSize(
      size: Size.square(widget.size),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              _square(_anim3, 0),
              _square(_anim4, 1),
              _square(_anim5, 2),
            ],
          ),
          Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              _square(_anim2, 3),
              _square(_anim3, 4),
              _square(_anim4, 5),
            ],
          ),
          Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              _square(_anim1, 6),
              _square(_anim2, 7),
              _square(_anim3, 8),
            ],
          ),
        ],
      ),
    );
  }

  Widget _square(Animation<double> animation, int index) {
    return ScaleTransition(
      scale: animation,
      child: SizedBox.fromSize(
          size: Size.square(widget.size / 3.0),
          child: Square(
            color: widget.color,
          )),
    );
  }
}

class Square extends StatelessWidget {

  final Color color;

  const Square({Key? key,required this.color}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color,
    );
  }
}

最终的效果如下:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老孟Flutter 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Loading动画系列
  • 最复杂的效果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档