PathMeasure的方法:
setPath(Path path, boolean forceClosed)/*计算长度的时候是否自动封闭路径*/)
/*计算路径的总长度*/
getLength()
/*计算距离路径起始点distance的位置的坐标和该点的正切值*/
getPosTan(float distance, float pos[], float tan[])
/*计算距离路径起始点distance的位置的坐标的矩阵*/
getMatrix(float distance, Matrix matrix, int flags)
/*从路径中截取距离起始点startD到stopD的新路径到dst中*/
getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo/*是否将起始点移动到startD的位置*/)
/*路径是否是闭合路径*/
isClosed()
/*该路径中的下一个路径*/
nextContour()
附上一个小例子:
package edo.com.design.view;
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.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
public class SearchView extends View {
private Paint mPaint;
private Path mSearchPath, mProgressPath;
private PathMeasure mMeasure;
// 当前的状态
private State mCurrentState;
private float mAnimatorValue = 0;
// 动画时间
private int mDefaultDuration;
private ValueAnimator mStartAnimator, mSearchAnimator, mEndAnimator;
public SearchView(Context context) {
this(context, null);
}
public SearchView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SearchView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
// 初始化
private void init() {
initPaint();
setupPath();
initAnimationListener();
mCurrentState = State.NONE;
startSearch();
}
// 开始搜索
public void startSearch() {
mHandler.sendEmptyMessage(0);
}
// 初始化动画监听器
private void initAnimationListener() {
mDefaultDuration = 2000;
mStartAnimator = ValueAnimator.ofFloat(0, 1.0f).setDuration(mDefaultDuration);
mStartAnimator.addUpdateListener(mUpdateListener);
mStartAnimator.addListener(mAnimatorListener);
mSearchAnimator = ValueAnimator.ofFloat(1.0f, 0).setDuration(mDefaultDuration);
mSearchAnimator.setRepeatCount(2);
mSearchAnimator.addUpdateListener(mUpdateListener);
mSearchAnimator.addListener(mAnimatorListener);
mEndAnimator = ValueAnimator.ofFloat(1.0f, 0).setDuration(mDefaultDuration);
mEndAnimator.addUpdateListener(mUpdateListener);
mEndAnimator.addListener(mAnimatorListener);
}
// 动画值变化监听
private ValueAnimator.AnimatorUpdateListener mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mAnimatorValue = (float) animation.getAnimatedValue();
postInvalidate();
}
};
// 动画监听
private ValueAnimator.AnimatorListener mAnimatorListener = new ValueAnimator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
mHandler.sendEmptyMessage(0);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
};
// 初始化画笔
private void initPaint() {
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(8);
mPaint.setAntiAlias(true);
// 路径计算器
mMeasure = new PathMeasure();
}
// 初始化路径
private void setupPath() {
// 进度条的路径
mProgressPath = new Path();
RectF r1 = new RectF(-100, -100, 100, 100);
mProgressPath.addArc(r1, 45, 359.9f);
// 放大镜的路径
mSearchPath = new Path();
RectF r2 = new RectF(-50, -50, 50, 50);
mSearchPath.addArc(r2, 45, 359.9f);
// 放大镜的手柄,连接到进度条的原点
float[] pos = new float[2];
mMeasure.setPath(mProgressPath, false);
mMeasure.getPosTan(0, pos, null);
mSearchPath.lineTo(pos[0], pos[1]);
}
// 动画控制器
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (mCurrentState) {
case NONE:
mCurrentState = State.STARTING;
mStartAnimator.start();
break;
case STARTING:
mCurrentState = State.SEARCHING;
mSearchAnimator.start();
break;
case SEARCHING:
mCurrentState = State.END;
mEndAnimator.start();
break;
case END:
mCurrentState = State.NONE;
break;
}
}
};
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth() / 2, getHeight() / 2);
canvas.drawColor(Color.parseColor("#0082D7"));
float length = 0, start = 0, end = 0;
Path destPath = new Path();
switch (mCurrentState) {
case NONE:
destPath = mSearchPath;
break;
case STARTING:
mMeasure.setPath(mSearchPath, false);
length = mMeasure.getLength();
mMeasure.getSegment(mAnimatorValue * length, length, destPath, true);
break;
case SEARCHING:
mMeasure.setPath(mProgressPath, false);
end = mMeasure.getLength() * mAnimatorValue;
start = end - (mAnimatorValue > 0.5f ? 1 - mAnimatorValue : mAnimatorValue) * 200.0f;
mMeasure.getSegment(start, end, destPath, true);
break;
case END:
mMeasure.setPath(mSearchPath, false);
length = mMeasure.getLength();
mMeasure.getSegment(mAnimatorValue * length, length, destPath, true);
break;
}
canvas.drawPath(destPath, mPaint);
}
private enum State {
NONE, STARTING, SEARCHING, END
}
}