Flutter 中如何绘制动画

栏目: Android · 发布时间: 6年前

内容简介:本文分享下自定义完成动画的实现方法,最终的效果图如下在Flutter中绘图非常简单。关键词

本文分享下自定义完成动画的实现方法,最终的效果图如下

Flutter 中如何绘制动画

源码地址

首先是绘图

在Flutter中绘图非常简单。关键词 CustomPainter , CustomPaint , Canvas

在iOS/Android中我们继承 UIView/View 重写 draw/onDraw 方法在里面执行画图操作。 在Flutter中稍微有点不一样,我们使用 CustomPaint (这是一个widget),它需要一个参数 painter ,这个参数的类型是一个抽象类 CustomPainter 。 我们需要实现这个类的两个关键方法: paint , shouldRepaint 。画什么就由 paint 决定,而只有 shouldRepaint 返回true的时候才会重绘。

实现 void paint(Canvas canvas, Size size) 这个方法,在iOS中我们使用 UIBezierPathCore Graphics 绘图,在Flutter具体的绘制方法用这个 canvas , 具体的API可以查看官方文档

下面这个例子就是画一段圆弧

class DemoPainter extends CustomPainter {
  final double _arcStart;
  final double _arcSweep;

  DemoPainter(this._arcStart, this._arcSweep);

  @override
  void paint(Canvas canvas, Size size) {
    double side = math.min(size.width, size.height);
    Paint paint = Paint()
      ..color = Colors.blue
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 4.0
      ..style = PaintingStyle.stroke;
    canvas.drawArc(
        Offset.zero & Size(side, side), _arcStart, _arcSweep, false, paint);
  }

  @override
  bool shouldRepaint(DemoPainter other) {
    return _arcStart != other._arcStart || _arcSweep != other._arcSweep;
  }
}
复制代码

使用的时候把 DemoPainter 的实例当做参数传给 CustomPaint 就可以使用了,比如

Container(
  child: CustomPaint(painter: DemoPainter(0.0, math.pi)),
  height: 200.0,
  width: 200.0,
  color: Colors.deepOrange,
  padding: EdgeInsets.all(30.0),
)
复制代码

显示效果

Flutter 中如何绘制动画

然后加动画

Flutter的动画也不复杂,关键词 AnimationController

Flutter中的动画是基于 Animation ,这个对象本身是一个抽象类,在一段时间内依次产生一些值。我们使用封装好的 AnimationController 来做动画,它在屏幕刷新的每一帧,产生一个新的值,默认情况是在给定的时间段内线性的生成0.0到1.0的数字。

AnimationController 有个参数 vsync 可以绑定到一个 widget (需要widget扩展 SingleTickerProviderStateMixin ),当widget不显示时,动画定时器将会暂停,当widget再次显示时,动画定时器重新恢复执行。 duration 属性可以设置持续时间。还有一些方法可以控制动画 forward 启动, reverse 反转, repeat 重复。

AnimationControlleraddListeneraddStatusListener 方法可以添加监听,一个是值监听一个是状态监听。值监听常用在调用 setState 来触发UI重建来实现动画,状态监听用在动画状态变化的时候执行一些方法,比如在动画结束时反转动画。

至此我们已经可以绘制动画了,代码如下

class DemoWidget extends StatefulWidget {
  @override
  _DemoWidgetState createState() => _DemoWidgetState();
}

class _DemoWidgetState extends State<DemoWidget>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    _controller =
        AnimationController(vsync: this, duration: Duration(milliseconds: 1500))
          ..repeat()
          ..addListener(() {
            setState(() {});
          });
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: DemoPainter(0.0, _controller.value * math.pi * 2),
    );
  }
}

复制代码
Flutter 中如何绘制动画

可以借助 AnimatedBuilder 改写上文的 initStatebuild 方法,使视图层级更加清楚,有助于封装

@override
  void initState() {
    _controller =
        AnimationController(vsync: this, duration: Duration(milliseconds: 1500))
          ..repeat();
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(animation: _controller, builder: (context, child) {
      return CustomPaint(
        painter: DemoPainter(0.0, _controller.value * math.pi * 2),
      );
    });
  }
复制代码

Tween与Curve

Tween 和Curve可以帮我们更好地控制Animation的值 一般的Animation会在给定的时间内线性的产生0.0到1.0的值

Tween可以把这些转变成我们想要的类型或者是范围 比如 Tween(begin: math.pi * 1.5, end: math.pi * 1.5 + math.pi * 2).evaluate(_controller), 就可以把值的范围转成1.5pi到3.5pi。

Curve是一个抽象类表示生成值的曲线,Curves已经定义了许多常用的曲线。

这里 Tween , Curve 可以使用 chain , evaluate , transform 和Animation串起来使用

我们可以使用这些更改我们上文的例子,代码如下

@override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: _controller,
        builder: (context, child) {
          return CustomPaint(
            painter: DemoPainter(
              Tween(begin: math.pi * 1.5, end: math.pi * 3.5)
                  .chain(CurveTween(curve: Interval(0.5, 1.0)))
                  .evaluate(_controller),
              math.sin(Tween(begin: 0.0, end: math.pi).evaluate(_controller)) *
                  math.pi,
            ),
          );
        });
  }
复制代码

当然这里第二个参数有更简洁的写法

math.sin(_controller.value*math.pi) *math.pi
复制代码

显示效果

Flutter 中如何绘制动画

本文版权属于再惠研发团队,欢迎转载,转载请保留出处。@白尔摩斯


以上所述就是小编给大家介绍的《Flutter 中如何绘制动画》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

软件人才管理的艺术

软件人才管理的艺术

Michael Lopp / 罗小平 / 人民邮电出版社 / 201008 / 35.00元

本书作者具有15年的硅谷人才管理经验,他在博客上发表了大量探讨软件人才的管理之道的文章,深受读者欢迎。本书素材取自他的博客文章,用深入浅出的语言,讲述发人深思的道理,具有很强的现实操作性。 本书分为三大部分:“管理的箭袋”、“过程就是产品”、“你的其他版本”。前两部分分别讲述了人员与产品的管理,第三部分除了讨论管理之外,还讲述了如何有针对性地准备简历和电话面试,来提高自己面试成功的几率。书中......一起来看看 《软件人才管理的艺术》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换