Android自定义View系列之Path绘制仿支付宝支付成功动画
前言
使用支付宝付款时,我们可以看到成功或者失败都会有个动画提示,如果我们需要做这样的效果的话,当然,你可以让设计师给你做个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地址:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。