Android 自定义View 之 Path PathMeasure (一)

Path

  • path常用api

moveTo(float x, float y) 移动下一次操作的起点位置
lineTo(float x, float y) 添加上一个点到当前点之间的直线到Path
addRect, addRoundRect, addOval, addCircle, addPath, addArc, arcTo 添加(矩形, 圆角矩形, 椭圆, 圆, 路径, 圆弧) 到当前Path
close() 连接第一个点连接到最后一个点,形成一个闭合区域
quadTo, cubicTo 分别为二次和三次贝塞尔曲线的方法
reset,rewind 清除Path中的内容(reset相当于重置到new Path阶段,rewind会保留Path的数据结构)

.....就不列完了,以上就是Path基本上在开发中是用的次数较多的api

PathMeasure

  • pathMeasure 常用Api

getLength() 返回当前轮廓的总长度,如果没有路径与此度量对象关联,则返回0。
getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) 给定起点和终点的距离,返回截取的中间段
setPath(Path path, boolean forceClosed) 将新的测量路径分配给一个新Path,如果null 则不显示。

这是最常用的测量PathMeasure Api

以下是结合项目中对Path 和 PathMeasure 的使用实例:

项目背景: 要求一个光标块在 矩形上移动,移动速度可更加手机充电速度变化,如下图

SVID_20200911_150113_1 (4).gif

相关API: addRoundRect(绘制矩形)setPath(赋值path路径)
reset(清除Path中的内容,清除之前的路径)getLength(获取路径的长度)
getSegment(截取一段path路径)

  • 关键代码

初始化矩形path并且测量这个path

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        segmentPath = new Path();
        path = new Path();
        path.addRoundRect(
                getPaddingLeft() + strokeWidth,
                getPaddingTop() + strokeWidth,
                getMeasuredWidth() - strokeWidth,
                getMeasuredHeight() - strokeWidth,
                100, 100, Path.Direction.CCW);
        pathMeasure.setPath(path, true);
    }

计算startD(截取片段开始位置) stopD(截取片段结束位置),截取到片段后赋值给新的Path(光标移动path)

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        segmentPath.reset();
        canvas.drawPath(path, paint);

        float length = pathMeasure.getLength();
        float stopD = mFloatPos * length;
        float startD = 0f;
        if (stopD < lineLength) {
            startD = 0;
        } else {
            startD = stopD - lineLength;
        }
        //截取片段
        pathMeasure.getSegment(startD, stopD, segmentPath, true);
        canvas.drawPath(segmentPath, segmentPaint);

        if (stopD < lineLength) {
            float mStart2 = length - (lineLength - stopD);
            pathMeasure.getSegment(mStart2, length, segmentPath, true);
            canvas.drawPath(segmentPath, segmentPaint);
        }
    }

开始动画,通过valueAnimator 动画,可以试试获取当前位置的信息 mFloatPost,然后通过mFloatPost
去计算StopD 的位置。

    public void startAnim() {
        if (valueAnimator == null) {
            valueAnimator = ValueAnimator.ofFloat(0, 1);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {


                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mFloatPos = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            valueAnimator.setDuration(4000);
            valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
            valueAnimator.setInterpolator(new LinearInterpolator());
            valueAnimator.start();
        }
    }

    public void stopAnim() {
        if (valueAnimator != null) {
            valueAnimator.cancel();
            valueAnimator = null;
        }
    }
..... 以上就关键代码
  • 使用方式
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        roundPathView = findViewById(R.id.round_path);
        roundPathView.startAnim();
    }
  @Override
    protected void onDestroy() {
        super.onDestroy();
        if (roundPathView!=null){
            roundPathView.stopAnim();
        }
    }

你可能感兴趣的:(Android 自定义View 之 Path PathMeasure (一))