Android Flutter绘制有趣的 loading加载动画

目录
  • 前言
  • 效果1:圆环内滚动的球
  • 效果2:双轨运动
  • 效果3:钟摆运动
  • 总结

前言

在网络速度较慢的场景,一个有趣的加载会提高用户的耐心和对 App 的好感,有些 loading 动效甚至会让用户有想弄清楚整个动效过程到底是怎么样的冲动。然而,大部分的 App的 loading 就是下面这种千篇一律的效果 —— 俗称“转圈”。

本篇我们利用Flutter 的 PathMetric来玩几个有趣的 loading 效果。

效果1:圆环内滚动的球

如上图所示,一个红色的小球在蓝色的圆环内滚动,而且在往上滚动的时候速度慢,往下滚动的时候有个明显的加速过程。这个效果实现的思路如下:

  • 绘制一个蓝色的圆环,在蓝色的圆环内构建一个半径更小一号的圆环路径(Path)。
  • 让红色小球在动画控制下沿着内部的圆环定义的路径运动。
  • 选择一个中间减速(上坡)两边加速的动画曲线。

下面是实现代码:

// 动画控制设置
controller =
  AnimationController(duration: const Duration(seconds: 3), vsync: this);
animation = Tween<double>(begin: 0, end: 1.0).animate(CurvedAnimation(
  parent: controller,
  curve: Curves.slowMiddle,
))
..addListener(() {
  setState(() {});
});

// 绘制和动画控制方法
_drawLoadingCircle(Canvas canvas, Size size) {
  var paint = Paint()..style = PaintingStyle.stroke
    ..color = Colors.blue[400]!
    ..strokeWidth = 2.0;
  var path = Path();
  final radius = 40.0;
  var center = Offset(size.width / 2, size.height / 2);
  path.addOval(Rect.fromCircle(center: center, radius: radius));
  canvas.drawPath(path, paint);

  var innerPath = Path();
  final ballRadius = 4.0;
  innerPath.addOval(Rect.fromCircle(center: center, radius: radius - ballRadius));
  var metrics = innerPath.computeMetrics();
  paint.color = Colors.red;
  paint.style = PaintingStyle.fill;
  for (var pathMetric in metrics) {
    var tangent = pathMetric.getTangentForOffset(pathMetric.length * animationValue);
    canvas.drawCircle(tangent!.position, ballRadius, paint);
  }
}

效果2:双轨运动

上面的实现效果其实比较简单,就是绘制了一个圆和一个椭圆,然后让两个实心圆沿着路径运动。因为有了这个组合效果,趣味性增加不少,外面的椭圆看起来就像是一条卫星轨道一样。实现的逻辑如下:

  • 绘制一个圆和一个椭圆,二者的中心点重合;
  • 在圆和椭圆的路径上分别绘制一个小的实心圆;
  • 通过动画控制实心圆沿着大圆和椭圆的路径上运动。

具体实现的代码如下所示。

controller =
      AnimationController(duration: const Duration(seconds: 2), vsync: this);
  animation = Tween<double>(begin: 0, end: 1.0).animate(CurvedAnimation(
    parent: controller,
    curve: Curves.easeInOutSine,
  ))
    ..addListener(() {
      setState(() {});
    });

_drawTwinsCircle(Canvas canvas, Size size) {
  var paint = Paint()
    ..style = PaintingStyle.stroke
    ..color = Colors.blue[400]!
    ..strokeWidth = 2.0;

  final radius = 50.0;
  final ballRadius = 6.0;
  var center = Offset(size.width / 2, size.height / 2);
  var circlePath = Path()
    ..addOval(Rect.fromCircle(center: center, radius: radius));
  paint.style = PaintingStyle.stroke;
  paint.color = Colors.blue[400]!;
  canvas.drawPath(circlePath, paint);

  var circleMetrics = circlePath.computeMetrics();
  for (var pathMetric in circleMetrics) {
    var tangent = pathMetric
        .getTangentForOffset(pathMetric.length * animationValue);

    paint.style = PaintingStyle.fill;
    paint.color = Colors.blue;
    canvas.drawCircle(tangent!.position, ballRadius, paint);
  }

  paint.style = PaintingStyle.stroke;
  paint.color = Colors.green[600]!;
  var ovalPath = Path()
    ..addOval(Rect.fromCenter(center: center, width: 3 * radius, height: 40));
  canvas.drawPath(ovalPath, paint);
  var ovalMetrics = ovalPath.computeMetrics();

  for (var pathMetric in ovalMetrics) {
    var tangent =
        pathMetric.getTangentForOffset(pathMetric.length * animationValue);

    paint.style = PaintingStyle.fill;
    canvas.drawCircle(tangent!.position, ballRadius, paint);
  }
}

效果3:钟摆运动

钟摆运动的示意图如下所示,一条绳子系着一个球悬挂某处,把球拉起一定的角度释放后,球就会带动绳子沿着一条圆弧来回运动,这条圆弧的半径就是绳子的长度。

这个效果通过代码来实现的话,需要做下面的事情:

  • 绘制顶部的横线,代表悬挂的顶点;
  • 绘制运动的圆弧路径,以便让球沿着圆弧运动;
  • 绘制实心圆代表球,并通过动画控制沿着一条圆弧运动;
  • 用一条顶端固定,末端指向球心的直线代表绳子;
  • 当球运动到弧线的终点后,通过动画反转(reverse)控制球 返回;到起点后再正向(forward) 运动就可以实现来回运动的效果了。

具体实现的代码如下,这里在绘制球的时候给 Paint 对象增加了一个 maskFilter 属性,以便让球看起来发光,更加好看点。

controller =
        AnimationController(duration: const Duration(seconds: 2), vsync: this);
animation = Tween<double>(begin: 0, end: 1.0).animate(CurvedAnimation(
  parent: controller,
  curve: Curves.easeInOutQuart,
))
  ..addListener(() {
    setState(() {});
  }
  ..addStatusListener((status) {
   if (status == AnimationStatus.completed) {
     controller.reverse();
   } else if (status == AnimationStatus.dismissed) {
     controller.forward();
   }
 });

_drawPendulum(Canvas canvas, Size size) {
  var paint = Paint()
    ..style = PaintingStyle.stroke
    ..color = Colors.blue[400]!
    ..strokeWidth = 2.0;

  final ceilWidth = 60.0;
  final pendulumHeight = 200.0;
  var ceilCenter =
      Offset(size.width / 2, size.height / 2 - pendulumHeight / 2);
  var ceilPath = Path()
    ..moveTo(ceilCenter.dx - ceilWidth / 2, ceilCenter.dy)
    ..lineTo(ceilCenter.dx + ceilWidth / 2, ceilCenter.dy);
  canvas.drawPath(ceilPath, paint);

  var pendulumArcPath = Path()
    ..addArc(Rect.fromCircle(center: ceilCenter, radius: pendulumHeight),
        3 * pi / 4, -pi / 2);

  paint.color = Colors.white70;
  var metrics = pendulumArcPath.computeMetrics();

  for (var pathMetric in metrics) {
    var tangent =
        pathMetric.getTangentForOffset(pathMetric.length * animationValue);

    canvas.drawLine(ceilCenter, tangent!.position, paint);
    paint.style = PaintingStyle.fill;
    paint.color = Colors.blue;
    paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 4.0);
    canvas.drawCircle(tangent.position, 16.0, paint);
  }
}

总结

本篇介绍了三种 Loading 动效的绘制逻辑和实现代码,可以看到利用路径属性进行绘图以及动画控制可以实现很多有趣的动画效果。

以上就是Android Flutter绘制有趣的 loading加载动画的详细内容,更多关于Android Flutter加载动画的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android中Market的Loading效果实现方法

    本文实例讲述了Android中Market的Loading效果实现方法.分享给大家供大家参考.具体如下: 在Android中,要实现Loading效果,一般情况下都使用ProgressDialog控件.ApiDemos/src/com/example/android/apis/view/ProgressBar3.java 提供两个demo: 仔细看了Android Market,发现却是不一样的,请看截图: 那到底如何实现呢?首先,我们创建一个布局文件, res/layout/fullscree

  • Android仿ios加载loading菊花图效果

    项目中经常会用到加载数据的loading显示图,除了设计根据app自身设计的动画loading,一般用的比较多的是仿照ios 的菊花加载loading 图,当然一些条件下还会涉及到加载成功/ 失败情况的显示,还有显示文字.   使用ProgressBar 来加载动画转圈,这里使用drawable文件 定义转圈动画, indeterminateDrawable 属性进行加载. <?xml version="1.0" encoding="utf-8"?> &

  • Android实现创意LoadingView动画效果

    Android上的热火锅煮萝卜蔬菜的Loading动画效果. 这是一个锅煮萝卜的Loading动画,效果仿照自之前IOS上看到的一个效果,觉得挺有意思,就移植过来了,在此完成了Dialog的样式,方便使用者作为LoadingView去使用. 关键性代码: package yellow5a5.demo.boilingloadingview.View; import android.animation.Animator; import android.animation.AnimatorListen

  • 三款Android炫酷Loading动画组件推荐

    最近突然心血来潮,对一些Loading感兴趣,Loading这玩意说重要也重要,说不重要也不重要,因为这是一个提升你产品体验的一个细节,如果loading做的好,对于一些耗时需要用户等待的页面来说会转移用户注意力,不会显得那么烦躁,所以你可以看到市面上各种各样好玩的Loading动画,那么这篇博客就准备收集下一些Loading动画吧,从这些实现思路上可以打开你们自己的思维,没准也会有创新好玩的Loading动画出现. 暂且先列举些最近GitHub新鲜出炉的Loading CircleProgre

  • 一看就喜欢的loading动画效果Android分析实现

    还是比较有新意,复杂度也不是非常高,所以就花时间整理一下,我们先一起看下原gif图效果: 从效果上看,我们需要考虑以下几个问题: 1.叶子的随机产生: 2.叶子随着一条正余弦曲线移动: 3.叶子在移动的时候旋转,旋转方向随机,正时针或逆时针: 4.叶子遇到进度条,似乎是融合进入: 5.叶子不能超出最左边的弧角: 7.叶子飘出时的角度不是一致,走的曲线的振幅也有差别,否则太有规律性,缺乏美感: 总的看起来,需要注意和麻烦的地方主要是以上几点,当然还有一些细节问题,比如最左边是圆弧等等: 那接下来我

  • Android自定义加载loading view动画组件

    在github上找的一个有点酷炫的loading动画https://github.com/Fichardu/CircleProgress 我写写使用步骤 自定义view(CircleProgress )的代码 package com.hysmarthotel.view; import com.hysmarthotel.roomcontrol.R; import com.hysmarthotel.util.EaseInOutCubicInterpolator; import android.ani

  • Android Flutter绘制有趣的 loading加载动画

    目录 前言 效果1:圆环内滚动的球 效果2:双轨运动 效果3:钟摆运动 总结 前言 在网络速度较慢的场景,一个有趣的加载会提高用户的耐心和对 App 的好感,有些 loading 动效甚至会让用户有想弄清楚整个动效过程到底是怎么样的冲动.然而,大部分的 App的 loading 就是下面这种千篇一律的效果 —— 俗称“转圈”. 本篇我们利用Flutter 的 PathMetric来玩几个有趣的 loading 效果. 效果1:圆环内滚动的球 如上图所示,一个红色的小球在蓝色的圆环内滚动,而且在往

  • Android 使用 Path 实现搜索动态加载动画效果

    今天实现一个搜索动态加载数据的动画效果,还是先看效果吧,用文字描述干巴巴的,看图说话什么都明白了, 实现这个就是使用Path中的getSegment()不断的去改变它截取片段的start和stop,再结合动画,今天就分步骤实现它,看完以后你也会觉的不是很难,只是没想到这么实现而已,所以要多见识,所谓眼界决定你的高度,还是延续我写博客的习惯,一步步分析,第一步就是绘制如下图: 如果单纯的绘制这个图很简单很简单的,绘制一个圆,然后再绘制一根线就搞定,但是要考虑这里的效果,就不能这么干了,如果你看了上

  • Android自定义view实现阻尼效果的加载动画

    效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振幅随时间逐渐衰减的振动,又称减幅振动.衰减振动.[1] 不论是弹簧振子还是单摆由于外界的摩擦和介质阻力总是存在,在振动过程中要不断克服外界阻力做功,消耗能量,振幅就会逐渐减小,经过一段时间,振动就会完全停下来.这种振幅随时间减小的振动称为阻尼振动.因为振幅与振动的能量有关,阻尼振动也就是能量不断减少的振动.阻尼振动是非简谐运

  • Android实现仿慕课网下拉加载动画

    具体实现方法就不多介绍了先附上源码,相信大家都容易看的懂: 这里为了让这个动画效果可被复用,于是就继承了ImageView 去实现某些方法 package com.example.loading_drawable; import android.content.Context; import android.graphics.drawable.AnimationDrawable; import android.util.AttributeSet; import android.util.Log;

  • 如何使用Flutter实现58同城中的加载动画详解

    前言 在应用中执行耗时操作时,为了避免界面长时间等待造成假死的现象,往往会添加一个加载中的动画来提醒用户,在58同城中也不例外,而且我们并没有使用系统默认的加载动画,而是制作了一个具有58特色的加载动画. 在本篇文章中,给大家分享下笔者使用Flutter实现58同城中加载动画的过程.先看一下加载动画的效果: 动画效果乍看比较复杂,难以看出端倪,其实我们可以先调慢动画的速度,这样能够比较清晰地分析出动画的流程. 动画的流程 动画由两个圆弧的动效组成,两个圆弧的起始点角度和扫过的弧度随着时间规律变化

  • Android自定义加载控件实现数据加载动画

    本文实例为大家分享了Android自定义加载控件,第一次小人跑动的加载效果眼前一亮,相比传统的PrograssBar高大上不止一点,于是走起,自定义了控件LoadingView去实现动态效果,可直接在xml中使用,具体实现如下 package com.*****.*****.widget; import android.content.Context; import android.graphics.drawable.AnimationDrawable; import android.util.

  • 漂亮实用的页面loading(加载)封装代码

    要做一个异步登录,打算给用户做一点提示,所以就网上找了点代码,自己修改新增了一些,做了一个html+css+js的功能封装,以备未来直接使用. html <!-- 缓冲提示条 --> <div class='buffer hidden' id='buffer' > <div class="spinner"> <span class='buffer_tip' id='buffer_tip' >正在登陆</span> <di

  • Android实现两圆点之间来回移动加载进度

    本文实例为大家分享了Android实现两圆点之间来回移动加载进度的具体代码,供大家参考,具体内容如下 一.前言 最近喜欢上自定义控件,喜欢实现一些简约有趣的控件,也好巩固下以前学得知识和不断的学习新知识,程序员嘛,活到老学到老. 这篇文章接着上一篇文章:Android_自定义控件之水平圆点加载进度条,类似的实现方式,都是些比较简单的view绘制. 二.实现 先看下实现的效果吧: 说下实现思路:圆点x轴会有个位移变化量,当位移达到圆点直径+圆点间距之和就回改变方向(改变方向就是通过变化量值不断增加

  • Android实现笑脸进度加载动画

    最近看到豆瓣的笑脸loading很有意思,看一张效果图: 下面分析一下如何实现这样的效果: 1.默认状态是一张笑脸的状态(一个嘴巴,两个眼睛,默认状态) 2.开始旋转,嘴巴追上眼睛(合并状态) 3.追上以后自转一周(自转状态) 4.然后逐渐释放眼睛(分离状态) 5.回到初始笑脸状态(默认状态) 一.默认状态 首先需要确定好嘴巴和眼睛的初始位置,我这里的初始化嘴巴是一个半圆,在横轴下方.眼睛分别与横轴夹角60度,如下图: 这两部分可以使用pathMeasure,我这里使用最简单的两个api:can

  • 基于Flutter制作一个吃豆人加载动画

    目录 效果图 绘制静态吃豆人.豆豆.眼睛 加入动画属性 总结 效果图 国际惯例,先看效果图: 具体效果就是吃豆人会根据吃不同颜色的豆子改变身体的颜色. 绘制静态吃豆人.豆豆.眼睛 首先,我们需要将这个静态的吃豆人绘制出来,我们可以把吃豆人看做是一个实心圆弧,豆豆和眼睛就是一个圆. 关键代码: //画头 _paint ..color = color.value ..style = PaintingStyle.fill; var rect = Rect.fromCenter( center: Off

随机推荐