可动态绘制PATH的VIEW,会动态显示整个绘制过程,可实现各种划线,复杂图形的动态绘制动画。
通过自定义VIEW和Path 路径动画实现。直接上代码:
PathView.java 自定义VIEW,直接放到XML里调用API就可以绘制
package com.ubt.animatortest.viewDrawer; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PathMeasure; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.View; /** * @日期: 2017/11/13 16:39 * @描述: 动态绘制路径动画 */ public class PathView extends View implements ValueAnimator.AnimatorUpdateListener{ private static final String TAG = "PathView"; private Paint mPaint; private Path dst; private float value; private Path mPath; private PathMeasure mPathMeasure; private ValueAnimator valueAnimator; private IPathAniamtion mPathListener; private Canvas mCanvas; private Bitmap mBitmap; public PathView(Context context) { this(context, null); } public PathView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public PathView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } private void initView() { dst = new Path(); mPathMeasure = new PathMeasure(); valueAnimator = ValueAnimator.ofFloat(0, 1); valueAnimator.addUpdateListener(this); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); if(mPathListener != null){ mPathListener.onAnimationEnd(); } } }); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //初始化bitmap和canvas mBitmap = Bitmap.createBitmap(getMeasuredWidth(),getMeasuredHeight(), Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(mPath != null) { drawBitmap(); canvas.drawBitmap(mBitmap, 0, 0, null); } } /** * 将路径绘制到bitmap上 */ private void drawBitmap(){ mPathMeasure.setPath(mPath, false); mPathMeasure.getSegment(0, value * mPathMeasure.getLength(), dst, true); mCanvas.drawPath(dst, mPaint); } @Override public void onAnimationUpdate(ValueAnimator animation) { value = (float) animation.getAnimatedValue(); invalidate(); } /** * 开始路径绘制动画 * @param path 需要绘制的路径 * @param duration 动画持续时长 * @param paint 画笔 */ public void startPathAnimator(@NonNull Path path, long duration, @NonNull Paint paint){ if(!valueAnimator.isRunning()) { mPath = path; mPaint = paint; valueAnimator.setDuration(duration); valueAnimator.start(); }else{ Log.e(TAG,"正在执行动画,此次忽略!!!"); } } /** * 设置动画回调 * @param iPathAniamtion */ public void setPathListener(IPathAniamtion iPathAniamtion){ mPathListener = iPathAniamtion; } }
IPathAniamtion.java 绘制完成回调
package com.ubt.animatortest.viewDrawer; /** * @日期: 2017/11/14 14:24 * @描述: 路径绘制动画接口 */ public interface IPathAniamtion { void onAnimationEnd(); }
TestViewFragmeng.java 调用DEMO
package com.ubt.animatortest.viewDrawer; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.Path; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.ubt.animatortest.R; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.Unbinder; /** * @日期: 2017/11/13 16:38 * @描述: */ public class TestViewFragment extends Fragment implements IPathAniamtion{ @BindView(R.id.myView) PathView myView; Unbinder unbinder; private Paint mPaint; private float mLineWidth = 10.0f; private Path mPath; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.view_test, container, false); initPaint(); initPath(); unbinder = ButterKnife.bind(this, view); myView.setPathListener(this); myView.startPathAnimator(mPath,1500, mPaint); return view; } @Override public void onDestroyView() { super.onDestroyView(); unbinder.unbind(); } private void initPaint() { mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStrokeWidth(mLineWidth); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.YELLOW); mPaint.setPathEffect(new DashPathEffect(new float[]{20f,10f}, 0)); } private void initPath(){ mPath = new Path(); mPath.moveTo(100, 100); mPath.cubicTo(300, 500, 400, 200, 500,500); } @Override public void onAnimationEnd() { mPath = new Path(); mPath.moveTo(500, 500); mPath.cubicTo(300, 500, 400, 200, 100,100); myView.startPathAnimator(mPath,1500, mPaint); } }