Flutter进阶—实现动画效果(二)

Flutter进阶—实现动画效果(二),第1张

概述在上一篇文章:Flutter进阶—实现动画效果(一)的最后,我们说到需要一个处理程序混乱的概念。在这一篇文章中,我们会引入补间,它是构建动画代码的一个非常简单的概念,主要作用是用面向对象的方法替代之前面向过程的方法。tween是一个值,它描述了其他值的空间中的两个点之间的路径,比如条形图的动画值从0运行到1。 补间在Dart中表示类型为Tween的对象 abstract class Tween<T

在上一篇文章:Flutter进阶—实现动画效果(一)的最后,我们说到需要一个处理程序混乱的概念。在这一篇文章中,我们会引入补间,它是构建动画代码的一个非常简单的概念,主要作用是用面向对象的方法替代之前面向过程的方法。tween是一个值,它描述了其他值的空间中的两个点之间的路径,比如条形图的动画值从0运行到1。

补间在Dart中表示类型为Tween的对象

abstract class Tween<T> {  final T begin;  final T end;  Tween(this.begin,this.end);  T lerp(double t);}

术语lerp来自计算机图形学领域,是线性插值(作为名词)和线性内插(作为动词)的缩写。参数t是动画值,补间应该从begin(当t为0时)到end(当t为1时)。

FlutterSDK的Tween类与Dart非常相似,但是一个支持变化begin和end的具体类。我们可以使用单个Tween来整理代码,用于处理条形图高度。

import 'package:Flutter/material.dart';import 'package:Flutter/animation.dart';import 'dart:math';voID main() {  runApp(new MyApp());}class MyApp extends StatelessWidget {  @overrIDe  Widget build(BuildContext context) {    return new MaterialApp(        Title: 'Flutter Demo',home: new MyHomePage(),);  }}class MyHomePage extends StatefulWidget {  @overrIDe  _MyHomePageState createState() => new _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> with TickerProvIDerStateMixin {  final random = new Random();  int dataSet = 50;  AnimationController animation;  Tween<double> tween;  @overrIDe  voID initState() {    super.initState();    animation = new AnimationController(        duration: const Duration(milliseconds: 300),vsync: this    );    // Tween({T begin,T end }):创建tween(补间)    tween = new Tween<double>(begin: 0.0,end: dataSet.todouble());    animation.forward();  }  @overrIDe  voID dispose() {    animation.dispose();    super.dispose();  }  voID changeData() {    setState(() {      dataSet = random.nextInt(100);      tween = new Tween<double>(        /* @overrIDe T evaluate( Animation<double> animation ) 返回给定动画的当前值的内插值 当动画值分别为0.0或1.0时,此方法返回begin和end */        begin: tween.evaluate(animation),end: dataSet.todouble()      );      animation.forward(from: 0.0);    });  }  @overrIDe  Widget build(BuildContext context) {    return new Scaffold(        body: new Center(          child: new CustomPaint(            size: new Size(200.0,100.0),/* Animation<T> animate( Animation<double> parent ) 返回一个由给定动画驱动的新动画,但它承担由该对象确定的值 */            painter: new barChartPainter(tween.animate(animation))          )        ),floatingActionbutton: new floatingActionbutton(            onpressed: changeData,child: new Icon(Icons.refresh),),);  }}class barChartPainter extends CustomPainter {  static const barWIDth = 10.0;  barChartPainter(Animation<double> animation)      : animation = animation,super(repaint: animation);  final Animation<double> animation;  @overrIDe  voID paint(Canvas canvas,Size size) {    final barHeight = animation.value;    final paint = new Paint()      ..color = colors.blue[400]      ..style = PaintingStyle.fill;    canvas.drawRect(        new Rect.fromLTWH(            size.wIDth-barWIDth/2.0,size.height-barHeight,barWIDth,barHeight        ),paint    );  }  @overrIDe  bool shouldRepaint(barChartPainter old) => false;}

我们使用Tween将条形高度动画终点包装在一个值中,它完全与AnimationController和CustomPainter进行接口,因为Flutter框架现在会在每个动画时间点上标记CustomPaint进行重绘,而不是将整个MyHomePage子树标记为重构、重新布局和重绘。这些都是显示的改进,但是,补间的概念不止如此,它提供了组织我们的想法和代码的结构。

回到我们的代码,我们需要一个bar类型和一个barTween来动画化它。我们将与bar相关的类提取到bar.dart文件中,放到main.dart同级目录下。

import 'package:Flutter/material.dart';import 'package:Flutter/animation.dart';import 'dart:ui' show lerpDouble;class bar {  bar(this.height);  final double height;  static bar lerp(bar begin,bar end,double t) {    return new bar(lerpDouble(begin.height,end.height,t));  }}class barTween extends Tween<bar> {  barTween(bar begin,bar end) : super(begin: begin,end: end);  @overrIDe  bar lerp(double t) => bar.lerp(begin,end,t);}class barChartPainter extends CustomPainter {  static const barWIDth = 10.0;  barChartPainter(Animation<bar> animation)      : animation = animation,super(repaint: animation);  final Animation<bar> animation;  @overrIDe  voID paint(Canvas canvas,Size size) {    final bar = animation.value;    final paint = new Paint()      ..color = colors.blue[400]      ..style = PaintingStyle.fill;    canvas.drawRect(        new Rect.fromLTWH(            size.wIDth-barWIDth/2.0,size.height-bar.height,bar.height        ),paint    );  }  @overrIDe  bool shouldRepaint(barChartPainter old) => false;}

我们遵循FlutterSDK的惯例来定义bar类的静态方法barTween.lerp。DartSDK中没有double.lerp,所以我们使用dart:ui包中的lerpDouble函数来达到同样的效果。

现在我们的应用程序可以用条形图重新显示。

import 'package:Flutter/material.dart';import 'package:Flutter/animation.dart';import 'dart:math';import 'bar.dart';voID main() {  runApp(new MyApp());}class MyApp extends StatelessWidget {  @overrIDe  Widget build(BuildContext context) {    return new MaterialApp(        Title: 'Flutter Demo',);  }}class MyHomePage extends StatefulWidget {  @overrIDe  _MyHomePageState createState() => new _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> with TickerProvIDerStateMixin {  final random = new Random();  AnimationController animation;  barTween tween;  @overrIDe  voID initState() {    super.initState();    animation = new AnimationController(        duration: const Duration(milliseconds: 300),vsync: this    );    tween = new barTween(new bar(0.0),new bar(50.0));    animation.forward();  }  @overrIDe  voID dispose() {    animation.dispose();    super.dispose();  }  voID changeData() {    setState(() {      tween = new barTween(        tween.evaluate(animation),new  bar(100.0 * random.nextDouble()),);      animation.forward(from: 0.0);    });  }  @overrIDe  Widget build(BuildContext context) {    return new Scaffold(        body: new Center(          child: new CustomPaint(            size: new Size(200.0,painter: new barChartPainter(tween.animate(animation))          )        ),);  }}

未完待续~~~

总结

以上是内存溢出为你收集整理的Flutter进阶—实现动画效果(二)全部内容,希望文章能够帮你解决Flutter进阶—实现动画效果(二)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1002678.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-22
下一篇2022-05-22

发表评论

登录后才能评论

评论列表(0条)

    保存