Flutter 中如何绘制动画

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

内容简介:本文分享下自定义完成动画的实现方法,最终的效果图如下在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 中如何绘制动画》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Blog Design Solutions

Blog Design Solutions

Richard Rutter、Andy Budd、Simon Collison、Chris J Davis、Michael Heilemann、Phil Sherry、David Powers、John Oxton / friendsofED / 2006-2-16 / USD 39.99

Blogging has moved rapidly from being a craze to become a core feature of the Internetfrom individuals sharing their thoughts with the world via online diaries, through fans talking about their favori......一起来看看 《Blog Design Solutions》 这本书的介绍吧!

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具