内容简介:还记得上一节 里面是怎么更新这一次我们使用看代码:
还记得上一节 里面是怎么更新 widget 的状态的吗?我们上次的步骤是:首先创建动画,然后给动画添加监听 addListener(...)
, 在 addListener(...)
方法中我们干了件 很重要 的事儿: setState((){})
,因为只有调用这个,才会让 widget 重绘。
这一次我们使用 AnimatedWidget
来实现动画,使用它就不需要给动画 addListener(...)
和 setState((){})
了, AnimatedWidget
自己会使用当前 Animation
的 value
来绘制自己。当然,这里 Animation
我们是以构造参数的方式传递进去的。
看代码:
class AnimatedContainer extends AnimatedWidget { AnimatedContainer({Key key, Animation<double> animation}) : super (key: key, listenable: animation); @override Widget build(BuildContext context) { final Animation<double> animation = listenable; return Center( child: Container( decoration: BoxDecoration( color: Colors.redAccent ), margin: EdgeInsets.symmetric(vertical: 10.0), height: animation.value, width: animation.value, ), ); } } 复制代码
上述代码中,我们定义了一个 AnimatedContainer
继承了 AnimatedWidget
,然后定义了一个构造方法,注意,构造方法中我们定义了一个 Animation
然后把这个 Animation
传到父类(super)中去了,我们可以看看 listenable: animation
这个参数,是一个 Listenable
类型,如下:
/// The [Listenable] to which this widget is listening. /// /// Commonly an [Animation] or a [ChangeNotifier]. final Listenable listenable; 复制代码
然后再看看 Animation 类:
abstract class Animation<T> extends Listenable implements ValueListenable<T> { ... } 复制代码
可以看到 Animation
是 Listenable
的子类,所以在我们自定义的 AnimatedContainer
类中可以传一个 Animation
类型的的参数作为父类中 listenable
的值。
使用我们上面定义的 AnimatedContainer
也很简单,直接作为 widget
使用就好,部分代码如下:
@override Widget build(BuildContext context) { return MaterialApp( title: 'AnimatedWidgetDemo', theme: ThemeData( primaryColor: Colors.redAccent ), home: Scaffold( appBar: AppBar( title: Text('AnimatedWidgetDemo'), ), body: AnimatedContainer(animation: animation,) ), );`` } 复制代码
可以看出我们在实例化 AnimatedContainer
的时候传入了一个 Animation
对象。
效果如下:
AnimatedBuilder
我们先看看如何使用 AnimatedBuilder
做一个上面一样的效果
部分代码如下:
@override Widget build(BuildContext context) { return MaterialApp( title: 'AnimatedBuilderExample', theme: ThemeData(primaryColor: Colors.redAccent), home: Scaffold( appBar: AppBar( title: Text('animatedBuilderExample'), ), body: Center( child: AnimatedBuilder( animation: _animation, child: Container( decoration: BoxDecoration(color: Colors.redAccent), ), builder: (context, child) { return Container( width: _animation.value, height: _animation.value, child: child, ); }, ), ), ), ); } 复制代码
因为 AnimatedBuilder
是继承于 AnimatedWidget
的,
class AnimatedBuilder extends AnimatedWidget { ... } 复制代码
所以可以直接把 AnimatedBuilder
当作 widget
使用
上述代码关键部分如下:
body: Center( child: AnimatedBuilder( animation: _animation, child: Container( decoration: BoxDecoration(color: Colors.redAccent), ), builder: (context, child) { return Container( width: _animation.value, height: _animation.value, child: child, ); }, ), ), 复制代码
效果如下:
builder
这个匿名类是每次动画值改变的时候就会被调用
AnimatedBuilder使用简化后的结构如下:
AnimatedBuilder( animateion: ... , child: ... , builder: (context, child) { return Container( width: ... , height: ... , child: child ) } ) 复制代码
上述代码看着可能会有迷糊的地方,里面的 child
好像被指定了两次,外面一个,里面一个。其实,外面的 child
是传给 AnimatedBuilder
的,而 AnimatedBuilder
又将这个 child
作为参数传递给了里面的匿名类( builder
)。
我们可以验证上述说明,就是给外面的 child
指定一个 key
,然后在 builder
里面打印出参数 child
的 key
。
body: Center( child: AnimatedBuilder( animation: _animation, child: Container( decoration: BoxDecoration(color: Colors.redAccent), key: Key("android"), ), builder: (context, child) { print("child.key: ${child.key}"); return Container( width: _animation.value, height: _animation.value, child: child, ); }, ), ), 复制代码
我们在外面的 child
里面的添加了一个 key
值,然后在 builder
里面打印出参数 child
的 key
值
输出如下:
flutter: child.key: [<'android'>] 复制代码
区别
我们来看看 AnimatedBuilder
AnimatedWidget
和添加 addListener{}
监听并在里面触发 setState(...)
这三种方式做动画有什么区别。
为了更直观的看出它们的区别,这里使用一个第三方控件: RandomContainer
,这个控件会在屏幕每次重绘的时候改变自身的颜色。
首先在 pubspec.yaml 中添加依赖 random_pk: any
,如下:
dependencies: flutter: sdk: flutter cupertino_icons: ^0.1.2 # RandomContainer random_pk: any 复制代码
先写一个小例子来看看 RandomContainer
这个控件每次在屏幕重绘的时候自身颜色改变的情况。
在屏幕上绘制一个宽高都为 200.0
的 RandomContainer
然后给 RandomContainer
添加点击事件,点击事件里面做的就是调用 setState(...)
让 widget 重绘,部分代码如下:
body: Center( child: GestureDetector( onTap: _changeColor, child: RandomContainer( width: 200.0, height: 200.0, ), ), ), 复制代码
使用 RandomContainer
的时候需要引入 import 'package:random_pk/random_pk.dart';
点击事件代码如下:
void _changeColor() { setState(() {}); } 复制代码
效果如下:
接下来我们使用三种方式实现同一种效果来看看有什么不同:
AnimatedWidget
_controller = AnimationController(vsync: this, duration: Duration(seconds: 5)) ..repeat(); 复制代码
@override Widget build(BuildContext context) { return MaterialApp( title: 'AnimatedBuilder', theme: ThemeData(primaryColor: Colors.redAccent), home: Scaffold( appBar: AppBar( title: Text('AnimatedBuilder'), ), body: Center( child: RandomContainer( width: 200.0, height: 200.0, child: AnimatedWidgetDemo( // new animation: _controller, ), ), ), ), ); } 复制代码
效果如下:
AnimatedBuilder
_controller = AnimationController(vsync: this, duration: Duration(seconds: 5)) ..repeat(); 复制代码
@override Widget build(BuildContext context) { return MaterialApp( title: 'AnimatedBuilder', theme: ThemeData(primaryColor: Colors.redAccent), home: Scaffold( appBar: AppBar( title: Text('AnimatedBuilder'), ), body: Center( child: RandomContainer( width: 200.0, height: 200.0, child: AnimatedBuilderDemo( // new child: getContainer(), animation: _controller, ), ), ), ), ); } 复制代码
AnimatedBuilder的效果和 AnimatedWidget 的效果是一样的。
接下来我们看看在 addListener{}
里面调用 setState(...)
的效果,也就是我们在上一节中实现动画的方式
_controller = AnimationController(vsync: this, duration: Duration(seconds: 5)) ..repeat() ..addListener(() { setState(() {}); }); 复制代码
@override Widget build(BuildContext context) { return MaterialApp( title: 'AnimatedBuilder', theme: ThemeData(primaryColor: Colors.redAccent), home: Scaffold( appBar: AppBar( title: Text('AnimatedBuilder'), ), body: Center( child: RandomContainer( width: 200.0, height: 200.0, child: Transform.rotate( // new child: getContainer(), angle: _controller.value * 2.0 * pi, ), ), ), ), ); } 复制代码
效果如下
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web应用安全权威指南
德丸浩 / 赵文、刘斌 / 人民邮电出版社 / 2014-10 / 79
《web应用安全权威指南》系日本web安全第一人德丸浩所创,是作者从业多年的经验总结。作者首先简要介绍了web应用的安全隐患以及产生原因,然后详细介绍了web安全的基础,如http、会话管理、同源策略等。此外还重点介绍了web应用的各种安全隐患,对其产生原理及对策进行了详尽的讲解。最后对如何提高web网站的安全性和开发安全的web应用所需要的管理进行了深入的探讨。本书可操作性强,读者可以通过下载已......一起来看看 《Web应用安全权威指南》 这本书的介绍吧!