flutter 动画展开菜单_Flutter 动画详解系列——隐式动画

上一篇文章Flutter 动画详解系列概述了下Flutter中的动画类型,及如何选择恰当的动画创建方式,接下来我们来看下最简单的动画,隐式动画。

系统的隐式动画Widget

在 Flutter 中的 Widgets 中有一部已经实现隐式动画Widget。如下图列出部分:

df0d688cd7ac

implicit_animation.png

首先我们来看一段未使用动画的代码:

bool _bigger = false;

@override

Widget build(BuildContext context) {

return Scaffold(

body: Column(

mainAxisAlignment: MainAxisAlignment.center,

children: [

Center(

child: Container(

width: _bigger ? 100 : 500,

height: 100,

color: Colors.red,

),

),

RaisedButton(

onPressed: () => setState(() {

_bigger = !_bigger;

}),

child: Icon(Icons.star),

),

],

),

);

}

df0d688cd7ac

未加动画效果时,矩形的形变会显得十分生硬,如果使用AnimatedContainer替换Container,增加一个动画的过渡效果:

Center(

child: AnimatedContainer(

width: _bigger ? 100 : 500,

height: 100,

color: Colors.red,

duration: Duration(seconds: 1),

),

),

df0d688cd7ac

整个过渡过程显得比较自然顺畅,我们通过新旧值之间的值进行动画处理的过程称为插值。每当旧值和新值发生变化时,AnimatedContainer便会处理其属性插值。

同样我们也可以通过插值来修改AnimatedContainer的其它属性,包括decoration的渐变色:

AnimatedContainer(

decoration: BoxDecoration(

gradient: RadialGradient(

colors: [Colors.purple, Colors.transparent],

stops: [ _bigger ? 0.2 : 0.5, 1.0])

),

),

上述代码很简单的演示如何使用 隐式动画Widget 来实现动画效果,非常的方便简单,但这也意味着可灵活性较差,在隐式动画Widget中,我们控制动画效果只能控制动画时长(Duration)和动画的曲线(Curve,具体的曲线效果可以参考 系统自带的曲线效果)。

AnimatedContainer(

width: _bigger ? 100 : 500,

child: Image.asset('assets/star.png'),

duration: Duration(seconds: 1),

curve: Curves.easeInOutQuint,

),

另外除了系统自带的曲线效果外,我们还可以通过继承Curve来实现自定义的曲线效果,如下实现了正弦曲线。

class SineCurve extends Curve {

final double count;

SineCurve({this.count = 1});

@override

double transformInternal(double t) {

return sin(count * 2 * pi * t) * 0.5 + 0.5;

}

}

小结

在Flutter中,系统已经提供了隐式动画的Widget,这些Widget是普通Widget的动画版本,我们可以通过 duration、curve来控制动画效果。

还有我们不一定需要通过StatefulWidget中使用setState来生成动画效果,我们也可以使用StreamBuilder和FutureBuilder来触发动画。

FutureBuilder(

future: future,

builder: (BuildContext context, AsyncSnapshot snapshot) {

double width;

switch(snapshot.connectionState) {

case ConnectionState.none:

case ConnectionState.waiting:

case ConnectionState.active:

width = 0;

break;

case ConnectionState.done:

width = 500;

break;

}

return AnimatedContainer(

width: width,

height: 100,

color: Colors.red,

duration: Duration(seconds: 1),

);

}

),

以上,如果Flutter框架提供给你的隐式动画Widget不能满足你的需求,那么进一步的话可以试试使用TweenAnimationBuilder来自定义创建隐式动画。

自定义隐式动画TweenAnimationBuilder

使用TweenAnimationBuilder,该 Widget 使用的时候我们需要传递 duration 参数动画时间、tween 参数动画要设置的值的范围(补间)、重要的还有 builder 参数,builder函数的参数包含context、补间参数tween的类型、还有child,让我们看一个简单的例子,红色的矩形框旋转360度:

TweenAnimationBuilder(

tween: Tween(begin: 0, end: 2 * pi),

duration: Duration(seconds: 2),

builder: (BuildContext context, double angle, Widget child) {

return Transform.rotate(

angle: angle,

child: Container(

color: Colors.red,

width: 100,

height: 100,

),

);

},

),

df0d688cd7ac

让我们再来看个例子,使用ColorFilered Wideget做一个图片渲染的效果。

TweenAnimationBuilder(

tween: ColorTween(begin: Colors.white, end: Colors.red),

duration: Duration(seconds: 2),

builder: (_, Color color, __) {

return ColorFiltered(

child: Image.asset('assets/sun.png'),

colorFilter: ColorFilter.mode(color, BlendMode.modulate),

);

},

)

df0d688cd7ac

通过Tween补间参数设置了从白色到红色的过渡,由颜色和图片的混合,另外如何补间参数可变的,所以如果补间参数是不变的话可以将参数声明为静态常量来使用。

static final colorTween = ColorTween(begin: Colors.white, end: Colors.red);

Center(

child: TweenAnimationBuilder(

tween: colorTween,

duration: Duration(seconds: 2),

builder: (_, Color color, __) {

return ColorFiltered(

child: Image.asset('assets/sun.png'),

colorFilter: ColorFilter.mode(color, BlendMode.modulate),

);

},

),

),

动态修改 Tween 参数

上面的例子中我们并没有调用setState,仅仅展示了动画从Tween的初始值到终值的简单动画效果,除此之外,我们还可以通过动态的修改Tween来实现动画效果:

class OngoingAnimationByModifyingEndTweenValue extends StatefulWidget {

@override

_OngoingAnimationState createState() => _OngoingAnimationState();

}

class _OngoingAnimationState extends State {

double _newValue = .4;

Color _newColor = Colors.white;

@override

Widget build(BuildContext context) {

return Stack(

children: [

starsBackground,

Column(

children: [

Center(

child: TweenAnimationBuilder(

tween: ColorTween(begin: Colors.white, end: _newColor),

duration: Duration(seconds: 2),

builder: (_, Color color, __) {

return ColorFiltered(

child: Image.asset('assets/sun.png'),

colorFilter: ColorFilter.mode(color, BlendMode.modulate),

);

},

),

),

Slider.adaptive(

value: _newValue,

onChanged: (double value) {

setState(() {

_newValue = value;

_newColor = Color.lerp(Colors.white, Colors.red, value);

});

},

),

],

),

],

);

}

}

首先我们声明一个_newColor 作为 Tween 的终值,通过滑动 Slider Widget,我们改变_newColor。调用setState每次的滑动都会使得动画更新。

另外,需要明确的一点事,TweenAnimationBuilder 的动画属性值是从当前值向最新的终值转变的。如上面的例子,当我们拖动 Slider 时,颜色变化相对于之前的颜色,而不是每次从最初的白色开始动画渐变。

TweenAnimationBuilder 总会将当前颜色到终值颜色平滑的动画过渡。所以如果改变的不是终值颜色而是开始颜色,动画效果是不会有区别的。

补充说明

除了上诉介绍的TweenAnimationBuilder参数外,我们还需要注意的参数还有:

curve,动画曲线,在上一篇文章Flutter 动画详解系列有过介绍。

动画完成的回调 onEnd :,我们可以在动画完成时完成指定的操作,如动画完成后显示另一个Widget。

child参数,child参数的设置其实也是一个潜在的性能优化项,正确的设置child,对动画性能的提升也是一大帮助。例子中虽然颜色发生了变化,但图片本身保持不变,但是当前代码是每次build都会重新创建Image Widget。针对此类的优化方式,我们可以提前创建图片,将图片作为参数传入,这样 Flutter 就知道每帧渲染时变化的是颜色,而不是图片本身。 当然因为例子本身简单,所以此优化不会有明显的效果,但当实现复杂动画效果时,慎重考虑child的实现,将会对你的动画性能带来一定的帮助。

总结

OK,以上就是对 Flutter 中的隐式动画的介绍了,包括系统自带的AnimatedFoo和TweenAnimationBuilder都有了一定的涉及。包括如何不通过使用StatefulWidget来实现动画效果、如何改变tween的终值产生顺滑的动画效果、如何提升TweenAnimationBuilder的动画性能时,我们可以设置tween参数时可以考虑设置为静态常量,设置child参数时可以考虑提前创建好child,作为参数传递。

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
<p> <span style="color:#333333;">Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的用户界面。本课程以理论+实例的方带领大家学习动画的基础理论及各种动画特效的编写。</span> </p> <p> <span style="color:#333333;"><strong>本次课程包含以下内容:<br /> 动画基本概念</strong><br /> <span style="color:#333333;">动画的本质</span><br /> <span style="color:#333333;">帧与FPS</span><br /> <span style="color:#333333;">插值器/估值器</span><br /> <span style="color:#333333;">动画类型</span><br /> <br /> <strong>动画相关核心类</strong><br /> <span style="color:#333333;">Animation介绍</span><br /> <span style="color:#333333;">AnimationController动画管理类</span><br /> <span style="color:#333333;">CurvedAnimation非线性动画</span><br /> <span style="color:#333333;">Tween补间值生成类</span><br /> <br /> <strong>动画事件监听及控制流程</strong><br /> <span style="color:#333333;">Listeners和StatusListeners动画监听</span><br /> <span style="color:#333333;">动画控制流程</span><br /> <br /> <strong>动画示例</strong><br /> <span style="color:#333333;">字体放大动画</span><br /> <span style="color:#333333;">缓动动画</span><br /> <span style="color:#333333;">遮罩动画</span><br /> <span style="color:#333333;">数字变化动画</span><br /> <span style="color:#333333;">图表动画</span><br /> <span style="color:#333333;">AnimatedOpacity实现渐变效果</span><br /> <span style="color:#333333;">Hero实现页面切换动画</span><br /> </span> </p>
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页