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 的使用实例:

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

在这里插入图片描述

相关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;
        }
    }
… 以上就关键代码
  • 使用方式
 <com.example.myapplication.RoundPathView
        android:id="@+id/round_path"
        android:layout_width="300dp"
        android:layout_height="500dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    @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();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值