Android 自定义View 矩形相关 沿着Path 进行规则运动 高阶PathMeasure

先上目的图

Android 自定义View 矩形相关 沿着Path 进行规则运动 高阶PathMeasure_第1张图片


先画矩形  由于这么这个效果要求啊 我决定用Path  ,如果要问为什么的话,那当直觉吧

先是画笔准备


        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(stroke_width);

        mPaint.setColor(Color.BLACK);

然后是准备宽高 ,这里由于不能直接在onDraw 里边操作,所以直接放进 要写的宽高转换一下就行了

 //放入事先的宽高
        int x=dip2px(context,300);
        int y=dip2px(context,100);
 public  int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

Path 规划路径,这里用二阶贝塞尔给他一个 圆角的 感觉

path = new Path();
        path.moveTo(x,y/2);
        path.lineTo(x, radiuRightTop);
        path.quadTo(x,0,x-radiuRightTop,0);
        path.lineTo(radiuRightTop,0);
        path.quadTo(0,0,0,radiuRightTop);
        path.lineTo(0,y/2);


        path2 = new Path();

        path2.moveTo(0,y/2);
        path2.lineTo(0, y-radiuRightTop);
        path2.quadTo(0,y,radiuRightTop,y);
        path2.lineTo(x-radiuRightTop,y);
        path2.quadTo(x,y,x,y-radiuRightTop);
        path2.lineTo(x,y/2);
 canvas.drawPath(path,mPaint);
        canvas.drawPath(path2,mPaint);

效果:

Android 自定义View 矩形相关 沿着Path 进行规则运动 高阶PathMeasure_第2张图片

这里可以明显的 到 圆角位置的 线比较粗

这里也是 问了几个大群,一顿的不耻下问

终于找到问题了,线宽问题:

这里的 圆角宽度实际上是 原始宽度,正确的宽度,一开始并没有考虑到线宽问题,现在重新修改一下 左边,就一个道理

在不影响 线的长度的情况下,修改宽度,也就是 X轴固定死 那就修改Y,Y轴固定死 那就修改X,总之你来回试吧,心诚则灵


        path.moveTo(x - stk_er, y / 2);
        path.lineTo(x - stk_er, radiuRightTop);
        path.quadTo(x, 0, x - radiuRightTop, 0 + stk_er);
        path.lineTo(radiuRightTop, 0 + stk_er);
        path.quadTo(0, 0, 0 + stk_er, radiuRightTop);
        path.lineTo(0 + stk_er, y / 2);


        path2 = new Path();

        path2.moveTo(0 + stk_er, y / 2);
        path2.lineTo(0 + stk_er, y - radiuRightTop);
        path2.quadTo(0, y, radiuRightTop, y - stk_er);
        path2.lineTo(x - radiuRightTop, y - stk_er);
        path2.quadTo(x, y, x - stk_er, y - radiuRightTop);
        path2.lineTo(x - stk_er, y / 2);

stk_er 是线宽的一半

然后就是让他动起来,需要用到PathMeasure 了

完整代码

public class MyLinearLayout extends LinearLayout {

    private final float stroke_width=10;
    private  float stk_er;
    private Paint mPaint;
    private Path mDst,mDst2;
    private int radiuRightTop=60;
    private float mLength,mLength2;
    private float mAnimatorValue;
    private PathMeasure mPathMeasure,mPathMeasure2;
    private boolean flag=true;
    private Bitmap bmp;
    private Path path;
    private Path path2;

    public MyLinearLayout(Context context) {
        this(context, null);
    }

    public MyLinearLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);


        stk_er=stroke_width/2;

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(stroke_width);

        mPaint.setColor(Color.BLACK);


        // 得到原始的图片
//        int x = getWidth();
//        int y = getHeight();

        //放入事先的宽高
        int x=dip2px(context,300);
        int y=dip2px(context,100);

        path = new Path();

        path.moveTo(x-stk_er,y/2);
        path.lineTo(x-stk_er, radiuRightTop);
        path.quadTo(x,0,x-radiuRightTop,0+stk_er);
        path.lineTo(radiuRightTop,0+stk_er);
        path.quadTo(0,0,0+stk_er,radiuRightTop);
        path.lineTo(0+stk_er,y/2);


        path2 = new Path();

        path2.moveTo(0+stk_er,y/2);
        path2.lineTo(0+stk_er, y-radiuRightTop);
        path2.quadTo(0,y,radiuRightTop,y-stk_er);
        path2.lineTo(x-radiuRightTop,y-stk_er);
        path2.quadTo(x,y,x-stk_er,y-radiuRightTop);
        path2.lineTo(x-stk_er,y/2);

        mPathMeasure = new PathMeasure();
        mPathMeasure.setPath(path, false);
        mLength = mPathMeasure.getLength();
        mDst=new Path();

        mPathMeasure2 = new PathMeasure();
        mPathMeasure2.setPath(path2, false);
        mLength2 = mPathMeasure2.getLength();
        mDst2=new Path();

        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mAnimatorValue = (float) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.setDuration(2000);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.start();



    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {

//        canvas.drawPath(path,mPaint);
//        canvas.drawPath(path2,mPaint);

        mDst.reset();
        float stop = mLength * mAnimatorValue;
        float start = (float) (stop - ((0.5 - Math.abs(mAnimatorValue - 0.5)) * mLength));
        mPathMeasure.getSegment(start, stop, mDst, true);

        canvas.drawPath(mDst, mPaint);

        mDst2.reset();
        float stop2 = mLength2 * mAnimatorValue;
        float start2 = (float) (stop2 - ((0.5 - Math.abs(mAnimatorValue - 0.5)) * mLength2));
        mPathMeasure2.getSegment(start2, stop2, mDst2, true);

        canvas.drawPath(mDst2, mPaint);



//        if(flag){
//
//            flag=false;
//        }

    }


    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}

XML 预先设定的宽高一致300 100

 

有个小坑啊 ,必须设置背景色 不然你会发现 啥也木有啊 ...


https://www.jianshu.com/p/3efa5341abcc  留个眼 这个效果没做出来  goPosTan


 

Android 自定义View 矩形相关 沿着Path 进行规则运动 高阶PathMeasure_第3张图片

public class MyLinearLayout extends LinearLayout {


    private Paint mPaint;
    private Path path;
    private PathMeasure mPathMeasure;
    private float mAnimatorValue;
    private float mLength;
    private float[] pos;
    private float[] tan;
    private Bitmap bitmap;

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

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.RED);
        mPaint.setStrokeWidth(5);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setAntiAlias(true);
        path = new Path();
        path.moveTo(0, 0);
        path.quadTo(100, 200, 200, 0);
        path.quadTo(300, -200, 400, 0);
        mPathMeasure = new PathMeasure(path, false);
        mLength = mPathMeasure.getLength();

        pos = new float[2];
        tan = new float[2];


        bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.boat);

        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.setDuration(5000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAnimatorValue = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.translate(200, 400);
        canvas.drawPath(path, mPaint);
        mPathMeasure.getPosTan(mLength * mAnimatorValue, pos, tan);
        float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI);
        canvas.rotate(degrees, pos[0], pos[1]);

        float left = pos[0] - bitmap.getWidth() / 2;
        float top = pos[1] - bitmap.getHeight() / 2;
//        float top = pos[1] - bitmap.getHeight() ;// 不除2会始终悬浮在 线上  俩种效果可以看一下

        canvas.drawBitmap(bitmap, left, top, mPaint);
        canvas.restore();
    }
}

是时候 粘贴了

mPathMeasure.getPosTan(mLength * mAnimatorValue, pos, tan);

 pos[]代表的就是当前的XY坐标

Android 自定义View 矩形相关 沿着Path 进行规则运动 高阶PathMeasure_第4张图片

 

一开始 船只能显示一般 以为呢 这个和上面那个不太一样,上面那个是MatchParent

这个是固定死的 所以要在  X,Y 的坐标上进行修改 和上面那个  stk_er 一个道理

最后的Path

    path.moveTo(x - stk_er-50, y / 2);
        path.lineTo(x - stk_er-50, radiuRightTop);
        path.quadTo(x-50, 0+50, x-50 - radiuRightTop, 0 + stk_er+50);
        path.lineTo(radiuRightTop+50, 0 + stk_er+50);
        path.quadTo(0+50, 0+50, 0 + stk_er+50, radiuRightTop);
        path.lineTo(0 + stk_er+50, y / 2);

把俩个都改一下

 path2 = new Path();

        path2.moveTo(0 + stk_er + margin, y / 2);
        path2.lineTo(0 + stk_er + margin, y - radiuRightTop);
        path2.quadTo(0 + margin, y - margin, radiuRightTop + margin, y - stk_er - margin);
        path2.lineTo(x - radiuRightTop - margin, y - stk_er - margin);
        path2.quadTo(x - margin, y - margin, x - stk_er - margin, y - radiuRightTop);
        path2.lineTo(x - stk_er - margin, y / 2);

这里我们一定是需要用到俩个画布 进行操作的

所以这里涉及到一个概念问题关于画布的 ,https://blog.csdn.net/toplist/article/details/6588278

找了很久最后得到一个模糊的结论 就是 new Canvas(bitmap),确保你的bitmap 是 可以被当做画布的,

可以这么写

 //android不允许直接修改res里面的图片,所以要用copy方法
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher).copy(Bitmap.Config.ARGB_8888,true);
        Canvas mCanvas = new Canvas(bitmap);

方法二 也是 比较常用的

bitmapCanvas = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        canvas2 = new Canvas(bitmapCanvas);

这里一个 重要概念 你用newCanvas 画完之后,一定要用

正牌的canvas ,在画一下

canvas.drawBitmap(bitmapCanvas, 0, 0, null);

这里可以看出,canvas 只是一个 对bitmap 进行操作的 临时工具,所以最后还是要把它的 bitmap 画出来


Android 自定义View 矩形相关 沿着Path 进行规则运动 高阶PathMeasure_第5张图片

public class MyLinearLayout extends View {


    private final float stroke_width = 10;
    private final int margin = 50;
    private float stk_er;
    private Paint mPaint;
    private int radiuRightTop = 100;
    private float mLength, mLength2;
    private float mAnimatorValue;
    private PathMeasure mPathMeasure, mPathMeasure2;
    private Bitmap bitmap;
    private Path path;
    private Path path2;
    private float[] pos;
    private float[] tan;
    private float[] pos1;
    private float[] tan1;
    private Canvas canvas2;
    private Bitmap bitmapCanvas;
    private int x;
    private int y;

    public MyLinearLayout(Context context) {
        this(context, null);
    }

    public MyLinearLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        stk_er = stroke_width / 2;

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(stroke_width);
        mPaint.setColor(Color.BLACK);

        // 得到原始的图片
//        int x = getWidth();
//        int y = getHeight();

        //放入事先的宽高
        x = dip2px(context, 300);
        y = dip2px(context, 100);


        path = new Path();

        path.moveTo(x - stk_er - margin, y / 2);
        path.lineTo(x - stk_er - margin, radiuRightTop);
        path.quadTo(x - margin, 0 + margin, x - margin - radiuRightTop, 0 + stk_er + margin);
        path.lineTo(radiuRightTop + margin, 0 + stk_er + margin);
        path.quadTo(0 + margin, 0 + margin, 0 + stk_er + margin, radiuRightTop);
        path.lineTo(0 + stk_er + margin, y / 2);


        path2 = new Path();

        path2.moveTo(0 + stk_er + margin, y / 2);
        path2.lineTo(0 + stk_er + margin, y - radiuRightTop);
        path2.quadTo(0 + margin, y - margin, radiuRightTop + margin, y - stk_er - margin);
        path2.lineTo(x - radiuRightTop - margin, y - stk_er - margin);
        path2.quadTo(x - margin, y - margin, x - stk_er - margin, y - radiuRightTop);
        path2.lineTo(x - stk_er - margin, y / 2);

        mPathMeasure = new PathMeasure();
        mPathMeasure.setPath(path, false);
        mLength = mPathMeasure.getLength();

        mPathMeasure2 = new PathMeasure();
        mPathMeasure2.setPath(path2, false);
        mLength2 = mPathMeasure2.getLength();

        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mAnimatorValue = (float) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.setDuration(2000);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
//        valueAnimator.start();

        pos = new float[2];
        tan = new float[2];

        pos1 = new float[2];
        tan1 = new float[2];

        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.boat);


    }

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

//        canvas.save();
        canvas.translate(0, 0);

        canvas.drawPath(path, mPaint);
        mPathMeasure.getPosTan(mLength * mAnimatorValue, pos, tan);

        float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI);
        canvas.rotate(degrees, pos[0], pos[1]);

        float left = pos[0] - bitmap.getWidth() / 2;
        float top = pos[1] - bitmap.getHeight() / 2;
//        float top = pos[1] - bitmap.getHeight() ;// 不除2会始终悬浮在 线上  俩种效果可以看一下

        canvas.drawBitmap(bitmap, left, top, mPaint);

//        canvas.restore();


        bitmapCanvas = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        canvas2 = new Canvas(bitmapCanvas);
//        canvas2.save();

        canvas2.translate(0, 0);
        canvas2.drawPath(path2, mPaint);
        mPathMeasure2.getPosTan(mLength2 * mAnimatorValue, pos1, tan1);

        float degrees2 = (float) (Math.atan2(tan1[1], tan1[0]) * 180.0 / Math.PI);
        canvas2.rotate(degrees2, pos1[0], pos1[1]);

        float left1 = pos1[0] - bitmap.getWidth() / 2;
        float top1 = pos1[1] - bitmap.getHeight() / 2;
//        float top = pos[1] - bitmap.getHeight() ;// 不除2会始终悬浮在 线上  俩种效果可以看一下

        canvas2.drawBitmap(bitmap, left1, top1, mPaint);

        canvas.drawBitmap(bitmapCanvas, 0, 0, null);
//        canvas2.restore();


    }


    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}

做一下修改

多虑了 直接注释去掉就可以

Android 自定义View 矩形相关 沿着Path 进行规则运动 高阶PathMeasure_第6张图片

package com.as.demo_touch;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.*;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;

/**
 * -----------------------------
 * Created by zqf on 2019/9/2.
 * ---------------------------
 */
public class MyLinearLayout extends View {


    private final float stroke_width = 10;
    private final int margin = 50;
    private float stk_er;
    private Paint mPaint;
    private int radiuRightTop = 100;
    private float mLength, mLength2;
    private float mAnimatorValue;
    private PathMeasure mPathMeasure, mPathMeasure2;
    private Bitmap bitmap;
    private Path path;
    private Path path2;
    private float[] pos;
    private float[] tan;
    private float[] pos1;
    private float[] tan1;
    private Canvas canvas2;
    private Bitmap bitmapCanvas;
    private int x;
    private int y;

    public MyLinearLayout(Context context) {
        this(context, null);
    }

    public MyLinearLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        stk_er = stroke_width / 2;

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(stroke_width);
        mPaint.setColor(Color.BLACK);

        // 得到原始的图片
//        int x = getWidth();
//        int y = getHeight();

        //放入事先的宽高
        x = dip2px(context, 300);
        y = dip2px(context, 100);


        path = new Path();

        path.moveTo(x - stk_er - margin, y / 2);
        path.lineTo(x - stk_er - margin, radiuRightTop);
        path.quadTo(x - margin, 0 + margin, x - margin - radiuRightTop, 0 + stk_er + margin);
        path.lineTo(radiuRightTop + margin, 0 + stk_er + margin);
        path.quadTo(0 + margin, 0 + margin, 0 + stk_er + margin, radiuRightTop);
        path.lineTo(0 + stk_er + margin, y / 2);


        path2 = new Path();

        path2.moveTo(0 + stk_er + margin, y / 2);
        path2.lineTo(0 + stk_er + margin, y - radiuRightTop);
        path2.quadTo(0 + margin, y - margin, radiuRightTop + margin, y - stk_er - margin);
        path2.lineTo(x - radiuRightTop - margin, y - stk_er - margin);
        path2.quadTo(x - margin, y - margin, x - stk_er - margin, y - radiuRightTop);
        path2.lineTo(x - stk_er - margin, y / 2);

        mPathMeasure = new PathMeasure();
        mPathMeasure.setPath(path, false);
        mLength = mPathMeasure.getLength();

        mPathMeasure2 = new PathMeasure();
        mPathMeasure2.setPath(path2, false);
        mLength2 = mPathMeasure2.getLength();

        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mAnimatorValue = (float) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.setDuration(2000);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.start();

        pos = new float[2];
        tan = new float[2];

        pos1 = new float[2];
        tan1 = new float[2];

        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.boat);

    }

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

        canvas.save();
        canvas.translate(0, 0);

        canvas.drawPath(path, mPaint);
        mPathMeasure.getPosTan(mLength * mAnimatorValue, pos, tan);

        float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI);
        canvas.rotate(degrees, pos[0], pos[1]);

        float left = pos[0] - bitmap.getWidth() / 2;
        float top = pos[1] - bitmap.getHeight() / 2;
//        float top = pos[1] - bitmap.getHeight() ;// 不除2会始终悬浮在 线上  俩种效果可以看一下

        canvas.drawBitmap(bitmap, left, top, mPaint);

        canvas.restore();


        bitmapCanvas = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        canvas2 = new Canvas(bitmapCanvas);
        canvas2.save();

        canvas2.translate(0, 0);
        canvas2.drawPath(path2, mPaint);
        mPathMeasure2.getPosTan(mLength2 * mAnimatorValue, pos1, tan1);

        float degrees2 = (float) (Math.atan2(tan1[1], tan1[0]) * 180.0 / Math.PI);
        canvas2.rotate(degrees2, pos1[0], pos1[1]);

        float left1 = pos1[0] - bitmap.getWidth() / 2;
        float top1 = pos1[1] - bitmap.getHeight() / 2;
//        float top = pos[1] - bitmap.getHeight() ;// 不除2会始终悬浮在 线上  俩种效果可以看一下

        canvas2.drawBitmap(bitmap, left1, top1, mPaint);

        canvas.drawBitmap(bitmapCanvas, 0, 0, null);
        canvas2.restore();


    }


    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}

在做修改,把画图 改为画线

Android 自定义View 矩形相关 沿着Path 进行规则运动 高阶PathMeasure_第7张图片

   canvas.save();
        canvas.translate(0, 0);

        mPaint.setColor(Color.BLACK);
        canvas.drawPath(path, mPaint);
        mPathMeasure.getPosTan(mLength * mAnimatorValue, pos, tan);

        float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI);
        canvas.rotate(degrees, pos[0], pos[1]);

        float left = pos[0] - bitmap.getWidth() / 2;
        float top = pos[1] - bitmap.getHeight() / 2;
//        float top = pos[1] - bitmap.getHeight() ;// 不除2会始终悬浮在 线上  俩种效果可以看一下

        mPaint.setColor(Color.RED);
        canvas.drawLine(pos[0], pos[1], left, top, mPaint);
        canvas.restore();


        bitmapCanvas = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        canvas2 = new Canvas(bitmapCanvas);
        canvas2.save();

        canvas2.translate(0, 0);
        mPaint.setColor(Color.BLACK);
        canvas2.drawPath(path2, mPaint);
        mPathMeasure2.getPosTan(mLength2 * mAnimatorValue, pos1, tan1);

        float degrees2 = (float) (Math.atan2(tan1[1], tan1[0]) * 180.0 / Math.PI);
        canvas2.rotate(degrees2, pos1[0], pos1[1]);

        float left1 = pos1[0] - bitmap.getWidth() / 2;
        float top1 = pos1[1] - bitmap.getHeight() / 2;
//        float top = pos[1] - bitmap.getHeight() ;// 不除2会始终悬浮在 线上  俩种效果可以看一下

         mPaint.setColor(Color.RED);
        canvas2.drawLine(pos1[0], pos1[1], left1, top1, mPaint);

        canvas.drawBitmap(bitmapCanvas, 0, 0, null);

        canvas2.restore();

线的方向不对先改方向,最后发现 这个实现方案不行~  太难了 ,,等找到解决方法再补上吧 ,先找个图顶上


 

Android 自定义View 矩形相关 沿着Path 进行规则运动 高阶PathMeasure_第8张图片

public class MyLinearLayout extends View {


    private final float stroke_width = 6;
    private final int margin = 26;
    private float stk_er;
    private Paint mPaint;
    private int radiuRightTop = 100;
    private float mLength, mLength2;
    private float mAnimatorValue;
    private PathMeasure mPathMeasure, mPathMeasure2;
    private Bitmap bitmap;
    private Path path;
    private Path path2;
    private float[] pos;
    private float[] tan;
    private float[] pos1;
    private float[] tan1;
    private Canvas canvas2;
    private Bitmap bitmapCanvas;
    private int x;
    private int y;

    public MyLinearLayout(Context context) {
        this(context, null);
    }

    public MyLinearLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        stk_er = stroke_width / 2;

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(stroke_width);
        mPaint.setColor(Color.WHITE);

        // 得到原始的图片
//        int x = getWidth();
//        int y = getHeight();

        //放入事先的宽高
        x = dip2px(context, 300);
        y = dip2px(context, 100);


        path = new Path();

        path.moveTo(x - stk_er - margin, y / 2);
        path.lineTo(x - stk_er - margin, radiuRightTop);
        path.quadTo(x - margin, 0 + margin, x - margin - radiuRightTop, 0 + stk_er + margin);
        path.lineTo(radiuRightTop + margin, 0 + stk_er + margin);
        path.quadTo(0 + margin, 0 + margin, 0 + stk_er + margin, radiuRightTop);
        path.lineTo(0 + stk_er + margin, y / 2);


        path2 = new Path();

        path2.moveTo(0 + stk_er + margin, y / 2);
        path2.lineTo(0 + stk_er + margin, y - radiuRightTop);
        path2.quadTo(0 + margin, y - margin, radiuRightTop + margin, y - stk_er - margin);
        path2.lineTo(x - radiuRightTop - margin, y - stk_er - margin);
        path2.quadTo(x - margin, y - margin, x - stk_er - margin, y - radiuRightTop);
        path2.lineTo(x - stk_er - margin, y / 2);

        mPathMeasure = new PathMeasure();
        mPathMeasure.setPath(path, false);
        mLength = mPathMeasure.getLength();

        mPathMeasure2 = new PathMeasure();
        mPathMeasure2.setPath(path2, false);
        mLength2 = mPathMeasure2.getLength();

        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mAnimatorValue = (float) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.setDuration(2000);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.start();

        pos = new float[2];
        tan = new float[2];

        pos1 = new float[2];
        tan1 = new float[2];

        ImageView imageView = new ImageView(context);
        imageView.setImageResource(R.drawable.line);


//        imageView.setDrawingCacheEnabled(true);
//        bitmap = Bitmap.createBitmap(imageView.getDrawingCache());
//        imageView.setDrawingCacheEnabled(false);

//        imageView.setBackground(context.getResources().getDrawable(R.drawable.line));
//
//        Drawable shape = getResources().getDrawable(R.drawable.line);
//        bitmap = Bitmap.createBitmap(shape.getIntrinsicWidth(),
//                shape.getIntrinsicHeight(),
//                shape.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
//
//        Canvas canvas = new Canvas(bitmap);
//        shape.setBounds(0, 0, shape.getIntrinsicWidth(), shape.getIntrinsicHeight());
//        shape.draw(canvas);




//        bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();


      bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.linexxxx);

    }

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

        canvas.save();
        canvas.translate(0, 0);

        canvas.drawPath(path, mPaint);
        mPathMeasure.getPosTan(mLength * mAnimatorValue, pos, tan);

        float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI);
        canvas.rotate(degrees, pos[0], pos[1]);

        float left = pos[0] - bitmap.getWidth() / 2;
        float top = pos[1] - bitmap.getHeight() / 2;
//        float top = pos[1] - bitmap.getHeight() ;// 不除2会始终悬浮在 线上  俩种效果可以看一下

        canvas.drawBitmap(bitmap, left, top, mPaint);
        canvas.restore();


        bitmapCanvas = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        canvas2 = new Canvas(bitmapCanvas);
        canvas2.save();

        canvas2.translate(0, 0);
        canvas2.drawPath(path2, mPaint);
        mPathMeasure2.getPosTan(mLength2 * mAnimatorValue, pos1, tan1);

        float degrees2 = (float) (Math.atan2(tan1[1], tan1[0]) * 180.0 / Math.PI);
        canvas2.rotate(degrees2, pos1[0], pos1[1]);

        float left1 = pos1[0] - bitmap.getWidth() / 2;
        float top1 = pos1[1] - bitmap.getHeight() / 2;
//        float top = pos[1] - bitmap.getHeight() ;// 不除2会始终悬浮在 线上  俩种效果可以看一下

        canvas2.drawBitmap(bitmap, left1, top1, mPaint);
        canvas.drawBitmap(bitmapCanvas, 0, 0, null);

        canvas2.restore();


    }


    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}

 

 

这里呢 有关那个小图  我是先用Shape 画出来 然后在 截图 ,开画图 改了一下 像素




    


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(安卓进阶,学习ing)