标签:
上礼拜上了一篇关于动画的自定义View的文章,然后里面的实现是PathMeasure,然后这一部分貌似以前没有讲过,那么就再补一篇来介绍下这部分的知识(之前一篇的传送门:http://blog.csdn.net/ddwhan0123/article/details/51066859)
直接说有点抽象,我们来看下演示的效果:
动的时候,是这样子
那暂停是这样子
其实这样的实现,一个个坐标增量画然后一直Invalidate也能做,但是写起来太麻烦,PathMeasure很好的解决了这部分问题。
PathMeasure的作用是什么?
测量路径的长度,也就是找到我们运行(或者说绘画)过程中的路径的点的集合。(再也不用找坐标啦!!)
我们要如何使用?
PathMeasure pathMeasure=new PathMeasure();
pathMeasure.setPath(path,true);
创建一个空对象,然后传入所需的路径和路径是否close掉了
当然也可以用另外一种构造函数,看你喜好了。
那么我们要如何获取途中的路径内容的操作?
执行 mPathMeasure.getPosTan(value, coords, null);
获取我们想要获取的坐标信息,然后在动画的有效区间里展现出来,OK我们来看下源码
包内容很简单,就一个自定义的View+寄存的Activity
package com.wjj.demo.view;
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;
import android.view.animation.DecelerateInterpolator;
import com.wjj.demo.R;
public class CustomView extends View {
ValueAnimator valueAnimator;
private PathMeasure mPathMeasure;
private Paint paint;
private Path path;
private float[] coords = new float[2];
private int XDraw, YDraw;
public CustomView(Context context) {
super(context);
init();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(10);
path = new Path();
path.moveTo(100, 100);
path.lineTo(500, 100);
path.lineTo(500, 500);
path.lineTo(100, 500);
path.lineTo(100, 100);
mPathMeasure = new PathMeasure(path, true);
coords = new float[2];
coords[0] = 100;
coords[1] = 100;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
XDraw = measureHandler(widthMeasureSpec);
YDraw = measureHandler(heightMeasureSpec);
setMeasuredDimension(XDraw, YDraw);
}
//尺寸测绘
private int measureHandler(int measureSpec) {
int vale = 520;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
vale = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
vale = Math.min(vale, specSize);
} else {
vale = 520;
}
return vale;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(getResources().getColor(R.color.plum));
canvas.drawPath(path, paint);
// 绘制对应目标
paint.setColor(getResources().getColor(R.color.Violet));
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(coords[0], coords[1], 20, paint);
}
// 开启动画
public void startAnim(long duration) {
valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength());
Log.d("-->measure length", "measure length = " + mPathMeasure.getLength());
valueAnimator.setDuration(duration);
// 减速插值器
valueAnimator.setInterpolator(new DecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
// 获取当前点坐标封装到coords
mPathMeasure.getPosTan(value, coords, null);
postInvalidate();
}
});
valueAnimator.start();
}
//停止动画
public void stopAnim() {
valueAnimator.cancel();
}
}
重要的步骤已经有注解了,插值器等内容在以前的文章有写过,不清楚或者忘记的可以看这里:http://blog.csdn.net/ddwhan0123/article/details/50464283
然后解释下为什么在最初就给了容器数组一个坐标,因为不那么做,点开始的地方是在(0,0)
代码地址:https://github.com/ddwhan0123/BlogSample/tree/master/PathMeasureDemo
下载地址:https://github.com/ddwhan0123/BlogSample/blob/master/PathMeasureDemo/PathMeasureDemo.zip
自定义View时,用到Paint Canvas的一些温故,讲讲用路径绘画实现动画效果(基础篇 三)
标签:
原文地址:http://blog.csdn.net/ddwhan0123/article/details/51121860