Android Path、贝塞尔曲线 自定义view

公司需求需要在每一段做暂停和播放 还有每一段时间不一样 ,所以不能整段用一个path和一个动画 ,那样时间就会根据整段的长度来平均总时间, 长度可以通过

pathMeasure = new PathMeasure();
mMovePath.lineTo(pointX[1], pointY[1]);
pathMeasure.setPath(mMovePath, false);
 
mLenght = (int) pathMeasure.getLength();
注意setpath第二个参数如果设置为true那么最后的长度 会有包含从终点到原点的直线距离

为了解决每一段能够实现不一样的时间走完 ,设置完第一段path后判断最后的点是否和下一段的起始点相似(差不多+-1px 因为不同分辨率的dip不相同则会导致可能有小数点)




public class SportLine extends View {
    private Paint mPaintBezier,mPaintrender;
    Paint mPaint;
    private Path mMovePath;
    private Path  renderPath;
    Path AllPath;
    private PathMeasure pathMeasure;
    //path路径的总长度
    private int mLenght;
    //当前路径的长度
    private int mCurrentPath;
    private float[] currentPosition;

    private Bitmap bitmap;
    int len01;
    int len02;
    int len03;
    int len04;
    int len05;
    int time01=5000;
    int time02=5000;
    int time03=5000;
    int time04=5000;
    int lentype=1;
    private float pointX[] = new float[6];
    private float pointY[] = new float[6];
    float pointXBezier[]=new float[4];
    float pointYBezier[]=new float[4];
    boolean isFirst =true;
    boolean issecond =true;
    boolean isThree =true;
    boolean isFourth =true;
    boolean isFifth =true;
    public SportLine(Context context) {
        super(context);
    }

    public SportLine(Context context, AttributeSet attrs) {
        super(context, attrs);

        currentPosition = new float[2];
        bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.sport_goingicon);
        mPaint=new Paint();
        //初始化画笔
        mPaintBezier=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintBezier.setStrokeWidth(DeviceUtils.getdimen2px(getContext(),R.dimen.dp_12));

//        int colorStart = getResources().getColor(R.color.colorPrimary);
//        int color1 = Color.GRAY;
//        int colorEnd = getResources().getColor(R.color.colorAccent);
//        LinearGradient backGradient = new LinearGradient(0, 0, 0, 10, new int[]{colorStart, color1 ,colorEnd}, null, Shader.TileMode.CLAMP);
//        mPaintBezier.setShader(backGradient);
        mPaintBezier.setStyle(Paint.Style.STROKE);
        mPaintBezier.setColor(getResources().getColor(R.color.sport_linebgcolor));
        mPaintBezier.setStrokeJoin(Paint.Join.ROUND);
        //线条结束处绘制一个半圆
        mPaintBezier.setStrokeCap(Paint.Cap.ROUND);
//        mPaintCircle=new Paint(Paint.ANTI_ALIAS_FLAG);
//        mPaintCircle.setStrokeWidth(8);
//        mPaintCircle.setStyle(Paint.Style.FILL_AND_STROKE);
//        mPaintCircle.setColor(Color.BLUE);

//        setOnClickListener(this);

        mPaintrender=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintrender.setStrokeWidth(DeviceUtils.getdimen2px(getContext(),R.dimen.dp_12));
        mPaintrender.setStyle(Paint.Style.STROKE);
        mPaintrender.setColor(getResources().getColor(R.color.sport_linecolor));
        mPaintrender.setStrokeJoin(Paint.Join.ROUND);
        mPaintrender.setStrokeCap(Paint.Cap.ROUND);
        Log.i(Constants.XQLOG,"dp_224="+DeviceUtils.getdimen2px(getContext(),R.dimen.dp_224)+"dp_626="+DeviceUtils.getdimen2px(getContext(), R.dimen.dp_626));

        pointX[0]=getdimen2px(getContext(), R.dimen.dp_40);
        pointY[0] = getdimen2px(getContext(), R.dimen.dp_626);

        pointX[1]=getdimen2px(getContext(), R.dimen.dp_224);
        pointY[1] = getdimen2px(getContext(), R.dimen.dp_626);

        pointX[2]=getdimen2px(getContext(), R.dimen.dp_410);
        pointY[2] = getdimen2px(getContext(), R.dimen.dp_140);

        pointX[3]=getdimen2px(getContext(), R.dimen.dp_595);
        pointY[3] = getdimen2px(getContext(), R.dimen.dp_140);

        pointX[4]=getdimen2px(getContext(), R.dimen.dp_780);
        pointY[4] = getdimen2px(getContext(), R.dimen.dp_626);

        pointX[5]=getdimen2px(getContext(), R.dimen.dp_964);
        pointY[5] = getdimen2px(getContext(), R.dimen.dp_626);




//        pointX[1]=getdimen2px(getContext(), R.dimen.dp_224);
//        pointY[1] = getdimen2px(getContext(), R.dimen.dp_626);
//
//        pointX[2]=getdimen2px(getContext(), R.dimen.dp_410);
//        pointY[2] = getdimen2px(getContext(), R.dimen.dp_140);
        pointXBezier[0]=getdimen2px(getContext(), R.dimen.dp_234);
        pointYBezier[0]=getdimen2px(getContext(), R.dimen.dp_560);

        pointXBezier[1]=getdimen2px(getContext(), R.dimen.dp_375);
        pointYBezier[1]=getdimen2px(getContext(), R.dimen.dp_144);
//        pointX[3]=getdimen2px(getContext(), R.dimen.dp_595);
//        pointY[3] = getdimen2px(getContext(), R.dimen.dp_140);
//
//        pointX[4]=getdimen2px(getContext(), R.dimen.dp_780);
//        pointY[4] = getdimen2px(getContext(), R.dimen.dp_626);
        pointXBezier[2]=getdimen2px(getContext(), R.dimen.dp_630);
        pointYBezier[2]=getdimen2px(getContext(), R.dimen.dp_146);

        pointXBezier[3]=getdimen2px(getContext(), R.dimen.dp_770);
        pointYBezier[3]=getdimen2px(getContext(), R.dimen.dp_540);
        renderPath =new Path();
        renderPath.moveTo(pointX[0],pointY[0]);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mMovePath=new Path();
        AllPath=new Path();

    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //画圆
        //canvas.drawCircle(mCircleX,mCircleY,30,mPaintCircle);

        //Path设置贝塞尔曲线,然后canvas        mMovePath.reset();
        AllPath.reset();
//        mMovePath.moveTo(mStartPointX,mStartPointY);
        /**
         * quadTo()绘制二阶贝塞尔曲线
         * cubicTo()绘制三阶贝塞尔曲线
         */
//        mMovePath.lineTo(mStartPointX,mStartPointY);
//        mMovePath.quadTo(mFlagPointX,mFlagPointY,mEndPointX-300,mEndPointY-100);
//        mMovePath.lineTo(mEndPointX-50,mEndPointY-100);
//        mMovePath.quadTo(mFlagPointX+50,mFlagPointY,mEndPointX,mEndPointY);
        //mMovePath.moveTo(100,200);
        //mMovePath.lineTo(150,200);
//        mMovePath.cubicTo(214,34,
//                220,26,
//                240,20);
        AllPath.moveTo(pointX[0], pointY[0]);
        AllPath.lineTo(pointX[1], pointY[1]);
        AllPath.cubicTo(
                pointXBezier[0], pointYBezier[0],
                pointXBezier[1], pointYBezier[1],
                pointX[2], pointY[2]);
        AllPath.quadTo(
                pointX[2], pointY[2],
                pointX[3],
                pointY[3]);
        AllPath.cubicTo(
               pointXBezier[2],pointYBezier[2],
                pointXBezier[3],pointYBezier[3],
               pointX[4], pointY[4]);

        AllPath.lineTo( pointX[5], pointY[5]);

        Log.i(Constants.XQLOG,"heigh:"+ getdimen2px(getContext(), R.dimen.dp_595));
        mLenght=0;

        pathMeasure = new PathMeasure();
        if(lentype==1) {
            mMovePath.moveTo(pointX[0], pointY[0]);
//        pathMeasure.setPath(mMovePath,true);
//        mLenght = (int) pathMeasure.getLength();
            mMovePath.lineTo(pointX[1], pointY[1]);
            pathMeasure.setPath(mMovePath, false);
            len01 = (int) pathMeasure.getLength() - mLenght;
            mLenght = (int) pathMeasure.getLength();//244
//        mLenght=244;
            Log.i(Constants.XQLOG, "len01=" + len01);
        }
        if(lentype==2){
            mMovePath.moveTo(pointX[1], pointY[1]);
            mMovePath.cubicTo(
                    pointXBezier[0], pointYBezier[0],
                    pointXBezier[1], pointYBezier[1],
                    pointX[2], pointY[2]);
            pathMeasure.setPath(mMovePath,false);
            len02 = (int) pathMeasure.getLength()-mLenght;
            mLenght = (int) pathMeasure.getLength();//878
            Log.i(Constants.XQLOG,"len02="+len02);
        }
        if(lentype==3){
            mMovePath.moveTo(pointX[2], pointY[2]);

            mMovePath.quadTo(
                    pointX[2], pointY[2],
                    pointX[3], pointY[3]);
            pathMeasure.setPath(mMovePath,false);
            len03 = (int) pathMeasure.getLength()-mLenght;
            mLenght = (int) pathMeasure.getLength();//1085
//        //mMovePath.cubicTo(300,26,308,34,370,200);
            Log.i(Constants.XQLOG,"len03="+len03);
        }
        if(lentype==4){
            mMovePath.moveTo(pointX[3], pointY[3]);
            mMovePath.cubicTo(
                    pointXBezier[2], pointYBezier[2],
                    pointXBezier[3], pointYBezier[3],
                    pointX[4], pointY[4]);
            pathMeasure.setPath(mMovePath,false);
            len04 = (int) pathMeasure.getLength()-mLenght;
            mLenght = (int) pathMeasure.getLength();//2244
            Log.i(Constants.XQLOG,"len04="+len04);
        }
        if(lentype==5){
            mMovePath.moveTo( pointX[4], pointY[4]);
            mMovePath.lineTo(pointX[5], pointY[5]);
            pathMeasure.setPath(mMovePath,false);
            len05 = (int) pathMeasure.getLength()-mLenght;
            mLenght = (int) pathMeasure.getLength();//1167
            Log.i(Constants.XQLOG,"len05="+len05);
        }


        if(lentype==1){
            mLenght=len01;
        }
//        else if(lentype==2){
        Log.i(Constants.XQLOG,"lentype="+2);
//当第一段path过后重新设置点和启动动画算时间 这个时候如何判断第二个点的启动 只能接近 不可能等于
        if(issecond&&(mCurrentPath <len01||mCurrentPath ==len01)&&((int)(currentPosition[0])== pointX[1]||((int)(currentPosition[0])== pointX[1]-1))
                &&
                ((int)(currentPosition[1])== pointY[1]||((int)(currentPosition[1])== pointY[1]-1)))
        {
            issecond=false;
            mLenght=len02;
            valueAnimator.cancel();
            valueAnimator=null;
            time=time01;
            startAnimator();
//            }
        }
        if(isThree&&(mCurrentPath <len02||mCurrentPath ==len02)&&((int)(currentPosition[0])== pointX[2]||((int)(currentPosition[0])== pointX[2]-1))
                &&
                ((int)(currentPosition[1])== pointY[2]||((int)(currentPosition[1])== pointY[2]-1)))
        {
            isThree=false;
            mLenght=len03;
            valueAnimator.cancel();
            valueAnimator=null;
            time=time02;
            startAnimator();
//            }
        }

        if(isFourth&&(mCurrentPath <len03||mCurrentPath ==len03)&&
                ((int)(currentPosition[0])== pointX[3]||((int)(currentPosition[0])== pointX[3]-1))
                &&
                ((int)(currentPosition[1])== pointY[3]||((int)(currentPosition[1])== pointY[3]-1))){
            isFourth =false;
            mLenght=len04;
            time=time03;
            valueAnimator.cancel();
            valueAnimator=null;
            startAnimator();
        }

        if(isFifth&&(mCurrentPath <len04||mCurrentPath ==len04)&&((int)(currentPosition[0])== pointX[4]||((int)(currentPosition[0])== pointX[4]-1))
                &&
                ((int)(currentPosition[1])==pointY[4]||((int)(currentPosition[1])==pointY[4]-1))){
            isFifth =false;
            mLenght=len05;
            time=time04;
            valueAnimator.cancel();
            valueAnimator=null;
            startAnimator();
        }

//        mMovePath.quadTo(190,70,220,20);
//        mMovePath.lineTo(200,50);
//        mMovePath.quadTo(220,70,270,100);

        canvas.drawPath(mMovePath,mPaintBezier);

        canvas.drawPath(AllPath,mPaintBezier);

        canvas.drawPath(renderPath,mPaintrender);
        if(mCurrentPath == 0 && currentPosition[0]==0 && currentPosition[1]==0){
            startAnimator();

        }else {
            Log.i(Constants.XQLOG,"bitmap currentPosition[0]="+currentPosition[0]+"bitmap currentPosition[1]="+currentPosition[1]);
            canvas.drawBitmap(bitmap, currentPosition[0] - bitmap.getWidth() / 2,
                    currentPosition[1] - bitmap.getHeight() / 2, mPaint);
        }
    }
    int time =5000;
    ValueAnimator valueAnimator;
    private void startAnimator(){
        valueAnimator = ValueAnimator.ofInt(0, mLenght);
        valueAnimator.setDuration(time);
//        valueAnimator.setRepeatCount(0);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentPath = (int) animation.getAnimatedValue();
                pathMeasure.getPosTan(mCurrentPath, currentPosition, null);
                renderPath.lineTo(currentPosition[0],currentPosition[1]);
                Log.i(Constants.XQLOG,"mCurrentPath="+mCurrentPath+"currentPosition[0]="+currentPosition[0]+"currentPosition[1]="+currentPosition[1]);

                if(((int)(currentPosition[0])== pointX[1]||((int)(currentPosition[0])== pointX[1]-1))
                        &&
                        ((int)(currentPosition[1])== pointY[1]||((int)(currentPosition[1])== pointY[1]-1))){

                    lentype=2;
//                    valueAnimator.cancel();
//                    valueAnimator=null;
                }

                if(((int)(currentPosition[0])== pointX[2]||((int)(currentPosition[0])== pointX[2]-1))
                        &&
                        ((int)(currentPosition[1])== pointY[2]||((int)(currentPosition[1])== pointY[2]-1)))
                {
                    lentype=3;
//                    valueAnimator.cancel();
//                    valueAnimator=null;
                }

                if(((int)(currentPosition[0])== pointX[3]||((int)(currentPosition[0])== pointX[3]-1))
                        &&
                        ((int)(currentPosition[1])== pointY[3]||((int)(currentPosition[1])== pointY[3]-1))){
                    lentype=4;
                }
                if(((int)(currentPosition[0])== pointX[4]||((int)(currentPosition[0])== pointX[4]-1))
                        &&
                        ((int)(currentPosition[1])== pointY[4]||((int)(currentPosition[1])== pointY[4]-1))){
                    lentype=5;
                }


                invalidate();



            }
        });
        valueAnimator.start();
    }

    public  void startRun(){
        valueAnimator.resume();

    }

    public   void stopRun(){
        valueAnimator.pause();
    }

    public void setTime(int time ,int time01,int time02,int time03,int time04){
        this.time =time;
        this.time01 =time01;
        this.time02 =time02;
        this.time03 =time03;
        this.time04 =time04;
    }

}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值