核心思路:利用PathMeasure,不断截取片段来画到canvas上
代码语言:javascript
复制/**
* 搜索动画效果2
*/
public class SearchAnimView2 extends View {
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//搜索图标的圆的半径
private float searchCircleRadius;
//搜索图标的线的长度
private float searchLineWidth;
//动画效果圆的半径
private float animeRadius;
//中心
private float centerY;
private float centerX;
//搜索图标消失动画
private final int status_dismiss_search = 1;
//加载动画
private final int status_progress = 2;
private int status = status_dismiss_search;
private float ratio;
private float ratio2;
//显示的长度
private float showLineWidth;
public SearchAnimView2(Context context) {
this(context, null);
}
public SearchAnimView2(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public SearchAnimView2(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(4);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
int size = getWidth() > getHeight() ? getHeight() : getWidth();
centerX = centerY = size / 2f;
searchCircleRadius = size / 6f;
searchLineWidth = size / 4f;
animeRadius = size / 2.2f;
showLineWidth = animeRadius / 3f;
}
@Override
protected void onDraw(Canvas canvas) {
//画搜索图标
if (status == status_dismiss_search) {
//画搜索圆
RectF oval = new RectF(centerX - searchCircleRadius, centerY - searchCircleRadius,
centerX searchCircleRadius, centerY searchCircleRadius);
if (ratio < 0.5f)
canvas.drawArc(oval, 45, 360 * ((0.5f - ratio) * 2f), false, mPaint);
//画线
canvas.save();
canvas.rotate(45, centerX, centerY);
if (ratio > 0.5f && ratio < 1f) {
canvas.drawLine(centerX searchCircleRadius, centerY,
centerX searchCircleRadius searchLineWidth * ((1f - ratio) * 2), centerY, mPaint);
} else {
canvas.drawLine(centerX searchCircleRadius, centerY,
centerX searchCircleRadius searchLineWidth, centerY, mPaint);
}
canvas.restore();
}
//画进度
if (status == status_progress) {
Path path = new Path();
RectF oval = new RectF(centerX - animeRadius, centerY - animeRadius,
centerX animeRadius, centerY animeRadius);
path.addArc(oval, 45, 359);
PathMeasure pathMeasure = new PathMeasure(path, false);
Path path2 = new Path();
pathMeasure.getSegment(pathMeasure.getLength() * ratio2,
pathMeasure.getLength() * ratio2 showLineWidth, path2, true);
canvas.drawPath(path2, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
startAnime();
return true;
}
return super.onTouchEvent(event);
}
ValueAnimator valueAnimator;
ValueAnimator valueAnimator2;
private void startAnime() {
valueAnimator = ValueAnimator.ofFloat(1f);
valueAnimator.setDuration(1000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
status = status_dismiss_search;
ratio = (float) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
status = status_progress;
valueAnimator2.start();
}
});
valueAnimator2 = ValueAnimator.ofFloat(1f);
valueAnimator2.setDuration(2000);
valueAnimator2.setInterpolator(new LinearInterpolator());
valueAnimator2.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator2.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
ratio2 = (float) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.start();
}
}
项目地址:https://gitee.com/aruba/CanvasApplication.git