今天实现一个搜索动态加载数据的动画效果,还是先看效果吧,用文字描述干巴巴的,看图说话什么都明白了,
实现这个就是使用Path中的getSegment()不断的去改变它截取片段的start和stop,再结合动画,今天就分步骤实现它,看完以后你也会觉的不是很难,只是没想到这么实现而已,所以要多见识,所谓眼界决定你的高度,还是延续我写博客的习惯,一步步分析,第一步就是绘制如下图:
如果单纯的绘制这个图很简单很简单的,绘制一个圆,然后再绘制一根线就搞定,但是要考虑这里的效果,就不能这么干了,如果你看了上面的gif图就知道,其实这是2个同心圆,然后前一个path的起点和后一个path的起点相连接就是形成一条直线了,但是path中的图形内容也就是这个圆是怎么绘制出来的呢?如果是绘制圆的话,上面的线起点和终点位置怎么去计算,这是个问题,但是我们绘制圆还可以使用绘制椭圆的形式也是可以绘制达到圆的效果,从45度开始绘制一个圆,是不是这个线的起点搞定了,分析图如下:
那么好,根据上面的分析开始写代码绘制出一个静态的搜索图:
package com.tuya; 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.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * Created by admin on 2016/12/17. */ public class DynamicSearchView2 extends View { private Paint paint; private int width;//view的宽度 private int height;//view的高度 private Path searchPath; private Path circlePath; private float BigCircleRectWidth;//搜索圆对应的外切正方形边长 private PathMeasure pathMeasure; private float[] pos; public DynamicSearchView2(Context context) { this(context,null); } public DynamicSearchView2(Context context, AttributeSet attrs) { this(context, attrs,0); } public DynamicSearchView2(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { paint = new Paint(); paint.setAntiAlias(true); paint.setStrokeWidth(3); paint.setColor(Color.WHITE); paint.setStyle(Paint.Style.STROKE); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); width = w; height = h; initPath(); } /** * 初始化path */ private void initPath() { searchPath = new Path(); circlePath = new Path(); if(width>height){ //长方形 BigCircleRectWidth = height; }else if(width<height){ BigCircleRectWidth = width; }else{ BigCircleRectWidth = width; } float smallbordWidth =BigCircleRectWidth/8; RectF searchRect = new RectF(-smallbordWidth,-smallbordWidth,smallbordWidth,smallbordWidth); searchPath.addArc(searchRect,45,360); float bigBordWidth = smallbordWidth*2; RectF circleRect = new RectF(-bigBordWidth,-bigBordWidth,bigBordWidth,bigBordWidth); circlePath.addArc(circleRect,45,-360); pathMeasure = new PathMeasure(circlePath,false); pos = new float[2]; pathMeasure.getPosTan(0,pos,null); searchPath.lineTo(pos[0],pos[1]); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.translate(width/2,height/2);//平移画布把这个view的中心点当做原点 canvas.drawPath(searchPath,paint); canvas.drawPath(circlePath,paint); } }
效果图:
本来这个外圆是不需要draw上去的,我在这绘制上去只是告诉你这二个圆是有一定的联系,哪为什么这根线是这样的呢?我们在绘制这个圆的时候是从45度开始绘制360刚好是一周,形成了一个圆,现在做个测试不要360,就写个330度,效果如下:
这个时候你会发现这条线是对的,导致问题其实是这样的,如图分析:
把绘制椭圆的关键代码:
searchPath.addArc(searchRect,45,358);
circlePath.addArc(circleRect,45,-358);
不要写成360,改为358试试,效果图:
发现这线是不是正常了,至于外面的圆还有点缺口,第一你可以把358改成359应该没事了,还有就是我们其实真实的效果并不需要这个外面的圆,所以不改也没事,那么好,第一步算是完成了,现在想想第二步怎么实现,先把第二步的效果用gif展示看下,不然光想没思路,就像你看美女,第一眼看那,是吧,就不多说了!要有画面感,
还是画布分析:
哪我们只要改变startD这个离起始点的位置值就ok,当然有很多种方法,但是android中基本上都是使用值动画,ok,根据这个思路实现这个第二步逻辑:
package com.tuya; import android.animation.Animator; 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.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * Created by admin on 2016/12/17. */ public class DynamicSearchView2 extends View { private Paint paint; private int width;//view的宽度 private int height;//view的高度 private Path searchPath; private Path circlePath; private float BigCircleRectWid