当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义View系列之Path绘制仿支付宝支付成功动画

Android自定义View系列之Path绘制仿支付宝支付成功动画

2019年07月24日  | 移动技术网移动技术  | 我要评论

前言

使用支付宝付款时,我们可以看到成功或者失败都会有个动画提示,如果我们需要做这样的效果的话,当然,你可以让设计师给你做个gif,但是我们知道图像比较耗内存的,我们自己可以用代码实现还是代码实现好点吧。

效果

实现方法

首先我们需要了解pathmeasure这个类,这个类我们可以理解为用来管理path。我们主要看几个方法。

pathmeasure(): 构造方法 ,实例化一个对象

pathmeasure(path path,boolean isclosed):传入path对象和是否闭合,path对象不能为空

getlength():获取当前轮廓、外形的总长度, 如果没有设置path对象,返回0

getsegment(float startd,float stopd,path dst,boolean startwithmoveto):调用这个方法,我们可以获取到指定范围内的一段轮廓,存入到dst参数中。所以,这个方法传入的参数分别为长度起始值、结束值、装这一段路径的path对象、是否moveto。另外,这个方法返回值为boolean类型,如果getlength为0的话,返回false,或者startd > stopd,同样返回false。

setpath(path path , boolean isclosed):给当前pathmeasure对象设置path

nextcontour():移动到下一个轮廓

然后我们需要动起来,我们知道invalidate()方法可以刷新界面,也就是重新调用ondraw()方法,所以我们要不停调用invalidate方法,在ondraw方法中改变参数,这样实现动的效果。所以可以用到刚刚介绍的getsegment方法,不断改变获取的范围,从0 * getlength,到1 * getlength,最后绘制完整。所以我们需要一个在一秒内或两秒内一个从0到1的值的变化,so,我们使用valueanimator这个类来实现。

//实例化对象
mcircleanimator = valueanimator.offloat(0, 1);
//设置时长为1000ms
mcircleanimator.setduration(1000);
//开始动画
mcircleanimator.start();
//设置动画监听
mcircleanimator.addupdatelistener(this);

动画开始后,在监听方法中获取当前进度并且重绘图像

mcirclepercent = (float)animation.getanimatedvalue();
invalidate();

在ondraw方法中,绘制图像

//画圆
mpathcircle.addcircle(getwidth() / 2, getwidth() / 2, getwidth() / 2 - mlinewidth, path.direction.cw);
mpathmeasure.setpath(mpathcircle, false);
mpathmeasure.getsegment(0, mcirclepercent * mpathmeasure.getlength(), mpathcircledst, true);
canvas.drawpath(mpathcircledst, mpaint);

附上源码,欢迎点评

package com.mintmedical.wavedemo;

import android.animation.valueanimator;
import android.content.context;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.paint;
import android.graphics.path;
import android.graphics.pathmeasure;
import android.util.attributeset;
import android.util.log;
import android.view.view;

/**
 * created by mooreli on 2016/12/12.
 */

public class resultanimation extends view implements valueanimator.animatorupdatelistener {
 private context mcontext;
 /**
  * paint对象
  */
 private paint mpaint;
 /**
  * path和对应的空path用来填充
  */
 private path mpathcircle;
 private path mpathcircledst;
 private path mpathright;
 private path mpathrightdst;
 private path mpathwrong1;
 private path mpathwrong2;
 private path mpathwrong1dst;
 private path mpathwrong2dst;
 /**
  * path管理
  */
 private pathmeasure mpathmeasure;
 /**
  * 动画
  */
 private valueanimator mcircleanimator;
 private valueanimator mrightanimator;
 private valueanimator mwrong1animator;
 private valueanimator mwrong2animator;
 /**
  * 当前绘制进度占总path长度百分比
  */
 private float mcirclepercent;
 private float mrightpercent;
 private float mwrong1percent;
 private float mwrong2percent;
 /**
  * 线宽
  */
 private int mlinewidth;
 /**
  * 正确动画 错误动画
  */
 public static final int result_right = 1;
 public static final int result_wrong = 2;
 /**
  * 当前结果类型
  */
 private int mresulttype = result_wrong;

 public resultanimation(context context) {
  super(context);
  mcontext = context;
  init();
 }

 public resultanimation(context context, attributeset attrs) {
  super(context, attrs);
  mcontext = context;
  init();
 }

 public resultanimation(context context, attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  mcontext = context;
  init();
 }

 private void init() {
  mlinewidth = dp2px(3);
  mpaint = new paint();
  mpaint.setantialias(true);
  mpaint.setstrokewidth(mlinewidth);
  mpaint.setstyle(paint.style.stroke);
  mpaint.setcolor(color.green);

  initpath();
 }

 private void initpath() {
  mpathcircle = new path();
  mpathcircledst = new path();
  mpathright = new path();
  mpathrightdst = new path();
  mpathwrong1 = new path();
  mpathwrong2 = new path();
  mpathwrong1dst = new path();
  mpathwrong2dst = new path();

  mpathmeasure = new pathmeasure();

  //实例化对象
  mcircleanimator = valueanimator.offloat(0, 1);
  //设置时长为1000ms
  mcircleanimator.setduration(1000);
  //开始动画
  mcircleanimator.start();
  //设置动画监听
  mcircleanimator.addupdatelistener(this);

  mrightanimator = valueanimator.offloat(0, 1);
  mrightanimator.setduration(500);
  mrightanimator.addupdatelistener(this);

  mwrong1animator = valueanimator.offloat(0, 1);
  mwrong1animator.setduration(300);
  mwrong1animator.addupdatelistener(this);
  mwrong2animator = valueanimator.offloat(0, 1);
  mwrong2animator.setduration(300);
  mwrong2animator.addupdatelistener(this);

 }

 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  if (mresulttype == result_right) {
   mpaint.setcolor(color.green);
  } else {
   mpaint.setcolor(color.red);
  }

  //画圆
  mpathcircle.addcircle(getwidth() / 2, getwidth() / 2, getwidth() / 2 - mlinewidth, path.direction.cw);
  mpathmeasure.setpath(mpathcircle, false);
  mpathmeasure.getsegment(0, mcirclepercent * mpathmeasure.getlength(), mpathcircledst, true);
  canvas.drawpath(mpathcircledst, mpaint);
  if (mresulttype == result_right) {
   //画对勾
   mpathright.moveto(getwidth() / 4, getwidth() / 2);
   mpathright.lineto(getwidth() / 2, getwidth() / 4 * 3);
   mpathright.lineto(getwidth() / 4 * 3, getwidth() / 4);
   if (mcirclepercent == 1) {
    mpathmeasure.nextcontour();
    mpathmeasure.setpath(mpathright, false);
    mpathmeasure.getsegment(0, mrightpercent * mpathmeasure.getlength(), mpathrightdst, true);
    canvas.drawpath(mpathrightdst, mpaint);
   }
  } else {
   mpathwrong1.moveto(getwidth() / 4 * 3, getwidth() / 4);
   mpathwrong1.lineto(getwidth() / 4, getwidth() / 4 * 3);

   mpathwrong2.moveto(getwidth() / 4, getwidth() / 4);
   mpathwrong2.lineto(getwidth() / 4 * 3, getwidth() / 4 * 3);

   if (mcirclepercent == 1) {
    mpathmeasure.nextcontour();
    mpathmeasure.setpath(mpathwrong1, false);
    mpathmeasure.getsegment(0, mwrong1percent * mpathmeasure.getlength(), mpathwrong1dst, true);
    canvas.drawpath(mpathwrong1dst, mpaint);
   }
   if (mwrong1percent == 1) {
    mpathmeasure.nextcontour();
    mpathmeasure.setpath(mpathwrong2, false);
    mpathmeasure.getsegment(0, mwrong2percent * mpathmeasure.getlength(), mpathwrong2dst, true);
    canvas.drawpath(mpathwrong2dst, mpaint);
   }
  }
 }

 private int dp2px(int dp) {
  float scale = mcontext.getresources().getdisplaymetrics().density;
  return (int) (scale * dp + 0.5f);
 }

 @override
 public void onanimationupdate(valueanimator animation) {
  //圆形动画
  if (animation.equals(mcircleanimator)) {
   mcirclepercent = (float) animation.getanimatedvalue();
   invalidate();
   log.e("test","percent:"+mcirclepercent);
   if (mcirclepercent == 1) {
    if (mresulttype == result_right)
     mrightanimator.start();
    else
     mwrong1animator.start();
   }
  }
  //正确时 对勾动画
  else if (animation.equals(mrightanimator)) {
   mrightpercent = (float) animation.getanimatedvalue();
   invalidate();
  }
  //错误时 右侧动画
  else if (animation.equals(mwrong1animator)) {
   mwrong1percent = (float) animation.getanimatedvalue();
   invalidate();
   if (mwrong1percent == 1) {
    mwrong2animator.start();
   }
  }
  //错误时 左侧动画
  else if (animation.equals(mwrong2animator)) {
   mwrong2percent = (float) animation.getanimatedvalue();
   invalidate();
  }
 }

 public void setmresulttype(int mresulttype) {
  this.mresulttype = mresulttype;
  invalidate();
 }

 /**
  * 固定写死了宽高,可重新手动调配
  *
  * @param widthmeasurespec
  * @param heightmeasurespec
  */
 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  super.onmeasure(widthmeasurespec, heightmeasurespec);
  setmeasureddimension(dp2px(50), dp2px(50));
 }
}

github地址:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网