PathMeasure

PathMeasure可用来画一些路径动画

比如这个搜索动画

下面看一下如何实现


先用path构造图形,分成两个path,里面的放大镜和外面的圆

path1 = new Path();
path1.addArc(100,100,300,300,44,359.9f);
path2 = new Path();
path2.addArc(150,150,250,250,45,359.9f);
path2.lineTo((float) (200 + 85 * Math.sin(45)),(float) (200 + 85 * Math.sin(45)));

再创建PathMeasure对象,并与path相关联

pathMeasure = new PathMeasure(path1,false);
pathMeasure2 = new PathMeasure(path2,false);

pathmeasure主要用到这两个函数

getLength()

Return the total length of the current contour, or 0 if no path is associated with this measure object.

getLength()返回路径即该pathMeasure相关联的path的长度

getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)

Given a start and stop distance, return in dst the intervening segment(s).

getSegment()函数可返回一个路径片段,第一个参数是路径的起点,第二个参数是路径的重点,第三个参数是返回的路径片段,第四个参数是

是否从起点开始,一般都是true


然后创建ValueAnimator

animator = ValueAnimator.ofFloat(0,1);
animator.setDuration(800);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
     @Override
     public void onAnimationUpdate(ValueAnimator animation) {
         float value = (float) animation.getAnimatedValue();
         dst2.reset();
         dst2.lineTo(0,0);
         float start = value * pathMeasure2.getLength();
         pathMeasure2.getSegment(start,pathMeasure2.getLength(),dst2,true);
         postInvalidate();
         }
     });

animator2 = ValueAnimator.ofFloat(0,1);
animator2.setDuration(1000);
animator2.setInterpolator(new AccelerateDecelerateInterpolator());
animator2.setRepeatCount(ValueAnimator.INFINITE);
animator2.setRepeatMode(ValueAnimator.RESTART);
animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
     @Override
     public void onAnimationUpdate(ValueAnimator animation) {
          float value = (float) animation.getAnimatedValue();
          dst.reset();
          dst.lineTo(0,0);
          float stop = value * pathMeasure.getLength();
          float start = (float) (stop - (0.5 - Math.abs(value - 0.5)) * pathMeasure.getLength());
          pathMeasure.getSegment(start,stop,dst,true);
          postInvalidate();
     }
});

animator.addListener(new Animator.AnimatorListener() {
     @Override
     public void onAnimationStart(Animator animation) {}

     @Override
     public void onAnimationEnd(Animator animation) {
	 animator2.start();
         state = State.searching;
     }

     @Override
     public void onAnimationCancel(Animator animation) {}

     @Override
     public void onAnimationRepeat(Animator animation) {}
});

animator1是放大镜逐渐消失的动画,animator2是外面的圆圈不断的转的动画

可以看到,再animator中不断的取值,不断的构造新的path片段,连接起来就构成了动画

完整代码如下

public class MyView extends View{

    private Path path1;
    private Path path2;
    private Path dst;
    private Path dst2;
    private PathMeasure pathMeasure;
    private PathMeasure pathMeasure2;
    private Paint paint;
    private ValueAnimator animator;
    private ValueAnimator animator2;

    public static enum State {ready,start,searching};
    private State state;

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        state = State.ready;
        dst = new Path();
        dst2 = new Path();
        path1 = new Path();
        path1.addArc(100,100,300,300,44,359.9f);
        path2 = new Path();
        path2.addArc(150,150,250,250,45,359.9f);
        path2.lineTo((float) (200 + 85 * Math.sin(45)),(float) (200 + 85 * Math.sin(45)));
        pathMeasure = new PathMeasure(path1,false);
        pathMeasure2 = new PathMeasure(path2,false);
        paint = new Paint();
        paint.setStrokeWidth(15);
        paint.setColor(Color.CYAN);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(Paint.Style.STROKE);

        initAnim();
    }

    public void initAnim(){
        animator = ValueAnimator.ofFloat(0,1);
        animator.setDuration(800);
        animator.setInterpolator(new AccelerateDecelerateInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                dst2.reset();
                dst2.lineTo(0,0);
                float start = value * pathMeasure2.getLength();
                pathMeasure2.getSegment(start,pathMeasure2.getLength(),dst2,true);
                postInvalidate();
            }
        });

        animator2 = ValueAnimator.ofFloat(0,1);
        animator2.setDuration(1000);
        animator2.setInterpolator(new AccelerateDecelerateInterpolator());
        animator2.setRepeatCount(ValueAnimator.INFINITE);
        animator2.setRepeatMode(ValueAnimator.RESTART);
        animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                dst.reset();
                dst.lineTo(0,0);
                float stop = value * pathMeasure.getLength();
                float start = (float) (stop - (0.5 - Math.abs(value - 0.5)) * pathMeasure.getLength());
                pathMeasure.getSegment(start,stop,dst,true);
                postInvalidate();
            }
        });

        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                animator2.start();
                state = State.searching;
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }


    public void startAnim(){
        state = State.start;
        animator.start();
    }

    public void endAnim(){
        if (animator != null) {
            animator.end();
        }
        if (animator2 != null) {
            animator2.end();
        }
        state = State.ready;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        switch (state){
            case ready:
                canvas.drawPath(path2,paint);
                break;
            case start:
                canvas.drawPath(dst,paint);
                canvas.drawPath(dst2,paint);
                break;
            case searching:
                canvas.drawPath(dst,paint);
                break;
        }
    }

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值