PathMeasure
概念:路径测量,一个用来测量path的工具类
常用API:Path长度测量,path跳转,path片段获取
效果一:
package com.example.testpathmeasure;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
/**
* @author writing
* @time 2019/12/23 13:51
* @note
*/
public class TestView extends View {
private Paint deafultPaint;
private Paint paint;
private int viewWidth;
private int viewHeight;
public TestView(Context context) {
super(context);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
deafultPaint = new Paint();
deafultPaint.setColor(Color.RED);
deafultPaint.setStrokeWidth(10);
deafultPaint.setStyle(Paint.Style.STROKE);
paint = new Paint();
paint.setColor(Color.DKGRAY);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//平移坐标系
canvas.translate(viewWidth / 2, viewHeight / 2);
//画坐标线
canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);
testForceClosed(canvas);
}
private void testForceClosed(Canvas canvas) {
Path path = new Path();
path.lineTo(0, 200);
path.lineTo(200, 200);
path.lineTo(200, 0);
//如果path是闭合状态,那么无论PathMeasure中的参数是true还是false,都是闭合状态。
//如果Path是非闭合状态,那么无论PathMeasure中的参数是true,则是闭合状态,false则是非闭合状态。
PathMeasure pathMeasure1 = new PathMeasure(path, false);
PathMeasure pathMeasure2 = new PathMeasure(path, true);
Log.i("zhang_xin", "length of false:" + pathMeasure1.getLength());
Log.i("zhang_xin", "length or true:" + pathMeasure2.getLength());
canvas.drawPath(path, deafultPaint);
}
}
看下打印输出
2019-12-23 14:40:28.234 21174-21174/? I/zhang_xin: length of false:600.0
2019-12-23 14:40:28.234 21174-21174/? I/zhang_xin: length or true:800.0
效果二:
package com.example.testpathmeasure;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
/**
* @author writing
* @time 2019/12/23 13:51
* @note
*/
public class TestView extends View {
private Paint deafultPaint;
private Paint paint;
private int viewWidth;
private int viewHeight;
public TestView(Context context) {
super(context);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
deafultPaint = new Paint();
deafultPaint.setColor(Color.RED);
deafultPaint.setStrokeWidth(10);
deafultPaint.setStyle(Paint.Style.STROKE);
paint = new Paint();
paint.setColor(Color.DKGRAY);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//平移坐标系
canvas.translate(viewWidth / 2, viewHeight / 2);
//画坐标线
canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);
testNextContour(canvas);
}
private void testNextContour(Canvas canvas) {
Path path0 = new Path();
Path path1 = new Path();
Path path2 = new Path();
//添加小矩形
path1.addRect(-100,-100,100,100, Path.Direction.CW);
PathMeasure pathMeasure1 = new PathMeasure(path1,false);
Log.i("zhang_xin","path1:"+pathMeasure1.getLength());
path2.addRect(-200,-200,200,200, Path.Direction.CW);
/**
* 对path1与path2进行布尔运算
* XOP保留path1与path2不共同的部分
*/
path0.op(path1,path2,Path.Op.XOR);
canvas.drawPath(path0,deafultPaint);
PathMeasure pathMeasure = new PathMeasure(path0,false);
Log.i("zhang_xin","length of pathMeasure:"+pathMeasure.getLength());
}
}
打印输出
2019-12-23 15:24:54.646 26441-26441/com.example.testpathmeasure I/zhang_xin: path1:800.0
2019-12-23 15:24:54.646 26441-26441/com.example.testpathmeasure I/zhang_xin: length of pathMeasure:1600.0
继续完善我们的代码
package com.example.testpathmeasure;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
/**
* @author writing
* @time 2019/12/23 13:51
* @note
*/
public class TestView extends View {
private Paint deafultPaint;
private Paint paint;
private int viewWidth;
private int viewHeight;
public TestView(Context context) {
super(context);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
deafultPaint = new Paint();
deafultPaint.setColor(Color.RED);
deafultPaint.setStrokeWidth(10);
deafultPaint.setStyle(Paint.Style.STROKE);
paint = new Paint();
paint.setColor(Color.DKGRAY);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//平移坐标系
canvas.translate(viewWidth / 2, viewHeight / 2);
//画坐标线
canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);
testNextContour(canvas);
}
private void testNextContour(Canvas canvas) {
Path path0 = new Path();
Path path1 = new Path();
Path path2 = new Path();
//添加小矩形
path1.addRect(-100,-100,100,100, Path.Direction.CW);
PathMeasure pathMeasure1 = new PathMeasure(path1,false);
Log.i("zhang_xin","path1:"+pathMeasure1.getLength());
path2.addRect(-200,-200,200,200, Path.Direction.CW);
Log.i("zhang_xin","path2:"+pathMeasure1.getLength());
/**
* 对path1与path2进行布尔运算
* XOP保留path1与path2不共同的部分
*/
path0.op(path1,path2,Path.Op.XOR);
canvas.drawPath(path0,deafultPaint);
PathMeasure pathMeasure = new PathMeasure(path0,false);
Log.i("zhang_xin","length of pathMeasure:"+pathMeasure.getLength());
float[] tan = new float[2];
float[] pos = new float[2];
/**
* diatance 指定Path路径上的长度
* 两个长度为2的浮点数组,这个数组是用来接收数据
* tan 当前位置的正切点的XY
* pos 当前Path路径点的XY
*/
pathMeasure.getPosTan(50f,pos,tan);
canvas.drawLine(tan[0],tan[1],pos[0],pos[1],paint);
Log.i("zhang_xin","tan[0]:"+tan[0]+",tan[1]:"+tan[1]+",pos[0]:"+pos[0]+",pos[1]:"+pos[1]);
//获取path的长度
float len1 = pathMeasure.getLength();
//跳转到下一个路径,由大矩形跳转到小矩形,大矩形与小矩形通过path.op()连接在一起
pathMeasure.nextContour();
pathMeasure.getPosTan(50f,pos,tan);
Log.i("zhang_xin","tan[0]:"+tan[0]+",tan[1]:"+tan[1]+",pos[0]:"+pos[0]+",pos[1]:"+pos[1]);
canvas.drawLine(tan[0],tan[1],pos[0],pos[1],deafultPaint);
float len2 = pathMeasure.getLength();
Log.i("zhang_xin","len1:"+len1);
Log.i("zhang_xin","len2:"+len2);
}
}
看下打印输出
2019-12-23 16:45:57.299 32583-32583/com.example.testpathmeasure I/zhang_xin: path1:800.0
2019-12-23 16:45:57.300 32583-32583/com.example.testpathmeasure I/zhang_xin: path2:1600.0
2019-12-23 16:45:57.301 32583-32583/com.example.testpathmeasure I/zhang_xin: length of pathMeasure:1600.0
2019-12-23 16:45:57.302 32583-32583/com.example.testpathmeasure I/zhang_xin: tan[0]:-1.0,tan[1]:0.0,pos[0]:150.0,pos[1]:-200.0
2019-12-23 16:45:57.302 32583-32583/com.example.testpathmeasure I/zhang_xin: tan[0]:-1.0,tan[1]:0.0,pos[0]:50.0,pos[1]:-100.0
2019-12-23 16:45:57.302 32583-32583/com.example.testpathmeasure I/zhang_xin: len1:1600.0
2019-12-23 16:45:57.303 32583-32583/com.example.testpathmeasure I/zhang_xin: len2:800.0
效果三
package com.example.testpathmeasure;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
/**
* @author writing
* @time 2019/12/23 13:51
* @note
*/
public class TestView extends View {
private Paint deafultPaint;
private Paint paint;
private int viewWidth;
private int viewHeight;
public TestView(Context context) {
super(context);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
deafultPaint = new Paint();
deafultPaint.setColor(Color.RED);
deafultPaint.setStrokeWidth(10);
deafultPaint.setStyle(Paint.Style.STROKE);
paint = new Paint();
paint.setColor(Color.DKGRAY);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//平移坐标系
canvas.translate(viewWidth / 2, viewHeight / 2);
//画坐标线
canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);
testGetSegment(canvas);
}
private void testGetSegment(Canvas canvas) {
Path path = new Path();
//添加一个顺时针的矩形
path.addRect(-200,-200,200,200, Path.Direction.CW);
Path dst = new Path();
//Path 与 PathMeasure关联
PathMeasure pathMeasure = new PathMeasure();
pathMeasure.setPath(path,true);
//截取一部分保存到dst中,并使用moveTo保持截取到的Path第一个点的位置不变
pathMeasure.getSegment(200,600,dst,true);
canvas.drawPath(path,paint);
canvas.drawPath(dst,deafultPaint);
}
}
效果四
看下true与false的区别
package com.example.testpathmeasure;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
/**
* @author writing
* @time 2019/12/23 13:51
* @note
*/
public class TestView extends View {
private Paint deafultPaint;
private Paint paint;
private int viewWidth;
private int viewHeight;
public TestView(Context context) {
super(context);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
deafultPaint = new Paint();
deafultPaint.setColor(Color.RED);
deafultPaint.setStrokeWidth(10);
deafultPaint.setStyle(Paint.Style.STROKE);
paint = new Paint();
paint.setColor(Color.DKGRAY);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//平移坐标系
canvas.translate(viewWidth / 2, viewHeight / 2);
//画坐标线
canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);
testGetSegmentMoveTo(canvas);
}
private void testGetSegmentMoveTo(Canvas canvas) {
Path path = new Path();
path.addRect(-200,-200,200,200, Path.Direction.CW);
Path dst = new Path();
dst.lineTo(300,300);
PathMeasure pathMeasure = new PathMeasure(path,false);
//tru与fasle会产生两种不同的效果
pathMeasure.getSegment(200,600,dst,true/false);
canvas.drawPath(path,paint);
canvas.drawPath(dst,deafultPaint);
}
}
为true的时候
为false的时候