Flutter Loading動畫系列中最復雜的一個效果

Loading動畫系列
github地址:https://github.com/LaoMengFlutter/flutter-do

最復雜的效果
我個人認為最復雜的,也是花費時間最長的動畫效果

放慢來看,是一個3x3的矩形,從左下角開始,每一斜排依次縮小,再還原的過程,下面就一步步實現,先繪制一個矩形:
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」 ,用于后面實現縮放
@override
??Widget?build(BuildContext?context)?{
????return?SizedBox.fromSize(
??????size:?Size.square(widget.size),
??????child:?Column(
????????mainAxisAlignment:?MainAxisAlignment.center,
????????mainAxisSize:?MainAxisSize.max,
????????children:?[
??????????Row(
????????????mainAxisSize:?MainAxisSize.max,
????????????mainAxisAlignment:?MainAxisAlignment.center,
????????????children:?[
??????????????_square(_anim3,?0),
??????????????_square(_anim4,?1),
??????????????_square(_anim5,?2),
????????????],
??????????),
??????????Row(
????????????mainAxisSize:?MainAxisSize.max,
????????????mainAxisAlignment:?MainAxisAlignment.center,
????????????children:?[
??????????????_square(_anim2,?3),
??????????????_square(_anim3,?4),
??????????????_square(_anim4,?5),
????????????],
??????????),
??????????Row(
????????????mainAxisSize:?MainAxisSize.max,
????????????mainAxisAlignment:?MainAxisAlignment.center,
????????????children:?[
??????????????_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依次完成,并不是同時完成,代碼如下:
_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)));
難點解決了,下面是完整的代碼:
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:?[
??????????Row(
????????????mainAxisSize:?MainAxisSize.max,
????????????mainAxisAlignment:?MainAxisAlignment.center,
????????????children:?[
??????????????_square(_anim3,?0),
??????????????_square(_anim4,?1),
??????????????_square(_anim5,?2),
????????????],
??????????),
??????????Row(
????????????mainAxisSize:?MainAxisSize.max,
????????????mainAxisAlignment:?MainAxisAlignment.center,
????????????children:?[
??????????????_square(_anim2,?3),
??????????????_square(_anim3,?4),
??????????????_square(_anim4,?5),
????????????],
??????????),
??????????Row(
????????????mainAxisSize:?MainAxisSize.max,
????????????mainAxisAlignment:?MainAxisAlignment.center,
????????????children:?[
??????????????_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,
????);
??}
}
最終的效果如下:


評論
圖片
表情
