自定义控件神器--PathMeasure

栏目: 后端 · 发布时间: 5年前

内容简介:自定义控件神器–PathMeasure我们平时自定义View的时候,经常会绘制path,想要求出path路径上的某个点的位置,很难通过一般的数学函数来计算,幸好系统给我们提供了一个PathMeasure可以用来测量一个path的路径,我们可以根据测量得到的值来绘制一些别的效果。PathMeasure有两个构造方法

自定义控件神器–PathMeasure

我们平时自定义View的时候,经常会绘制path,想要求出path路径上的某个点的位置,很难通过一般的数学函数来计算,幸好系统给我们提供了一个PathMeasure可以用来测量一个path的路径,我们可以根据测量得到的值来绘制一些别的效果。

PathMeasure有两个构造方法

public PathMeasure() {
      mPath = null;
      native_instance = native_create(0, false);
  }
public PathMeasure(Path path, boolean forceClosed) {
      mPath = path;
      native_instance = native_create(path != null ? path.readOnlyNI() : 0,forceClosed);
  }

一个是有参数的,一个是没参数的

pathMeasure.setPath(mPath,false);

下面来看PathMeasure中的几个比较常用的方法

getSegment

给定一个起始点,一个结束点和一个空path对象,把给定的起点到终点的路径赋值给这个空的path。 public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) 。最后一个参数startWithMoveTo表示起点是否使用moveTo,用来保证截取的path第一个点的位置不变。从而保证截取的片段不会变形

它返回的是一个boolean值,如果截取到的路径长度是0就返回false,不是0就返回true。

下面来看一下使用getSegment的简单案例,在onDraw方法中

mPath.reset();
mFloat += 0.01;
if (mFloat >= 1){
    mFloat = 0;
}
mPath.addCircle(getWidth()/2,getHeight()/2,200,Path.Direction.CW);
mDst.reset();
pathMeasure.setPath(mPath,false);
float distance = pathMeasure.getLength() * mFloat;
pathMeasure.getSegment(0, distance , mDst, true);
canvas.drawPath(mDst, mPaint);
invalidate();

使用一个0-1的成员变量mFloat来控制当前截取比例,每次调用invalidate的时候mFloat的值都会改变,这样就可以弄个简单的动画效果 效果如下

自定义控件神器--PathMeasure

上面一直是从0来时截取如果我们改一下截取的位置

pathMeasure.getSegment(2*distance/3, distance, mDst, true);

第一个参数改成了 2*distance/3 ,效果如下,类似一个加载动画的效果,这个参数可以随便改,更改的不同截取效果就不同

自定义控件神器--PathMeasure

前面两个我们只绘制了我们截取的path,下面把原path也绘制上,截取的部分换一种颜色绘制,效果如下

自定义控件神器--PathMeasure

getPosTan

getPosTan方法,可以获得path路径上某个点的位置和这个点的切线的值。 public boolean getPosTan(float distance, float pos[], float tan[]) distance是当前需要截取的长度,pos是一个数组,如果不为空,可以给这个数组赋值,pos[0]是x坐标pos[1]是y坐标,tan跟也是个数组,tan[0],tan[1]代表切线的值,通过Math.atan2()方法传入tan[0],tan[1]可以获取到当前切线的角度。

下面看一个简单的例子

mPath.reset();

  mFloat += 0.01;
  if (mFloat >= 1){
      mFloat = 0;
  }
 mPath.addCircle(getWidth()/2,getHeight()/2,200,Path.Direction.CW);
  pathMeasure.setPath(mPath,false);
 //用来记录位置
  float []pos = new float[2];
  //用来记录切点的位置
  float []tan = new float[2];
  float distance = pathMeasure.getLength() * mFloat;
  pathMeasure.getPosTan(distance,pos,tan);
  //计算出当前图片要旋转的角度
  float degree = (float) (Math.atan2(tan[1], tan[0]) * 180 / Math.PI);
  mMatrix.reset();
  //设置旋转角度和旋转中心
  mMatrix.postRotate(degree,mBitmap.getWidth() / 2,mBitmap.getHeight() / 2);
  //设置绘制的中心点与当前图片中心点重合
  mMatrix.postTranslate(pos[0]-mBitmap.getWidth() / 2,pos[1]-mBitmap.getHeight()/2);
  canvas.drawPath(mPath, mPaint);
  canvas.drawBitmap(mBitmap,mMatrix, mPaint);

效果如下:

自定义控件神器--PathMeasure

通过getPosTan方法,获取到当前的角度,通过Matrix方法把一个图片旋转这个角度,然后绘制到圆圈上

除了使用getPosTan之外,还有一个稍微简单的方法可以获取到pos和tan的值,通过 pathMeasure.getMatrix 方法

public boolean getMatrix(float distance, Matrix matrix, int flags)

前两个值好理解,最后一个值flag,用来指定矩阵中需要返回那些参数,有两个值

public static final int POSITION_MATRIX_FLAG = 0x01;

public static final int TANGENT_MATRIX_FLAG = 0x02;

这两个值分别代表前面的pos和tan,例如下面的代码

mPath.reset();
 mFloat += 0.01;
 if (mFloat >= 1){
     mFloat = 0;
 }
 //路径
 mPath.lineTo(0, 200);
 mPath.lineTo(300, 200);
 mPath.quadTo(450,100,600,200);
 mPath.lineTo(900, 200);
 pathMeasure.setPath(mPath,false);
 //将pos信息和tan信息保存在mMatrix中
 pathMeasure.getMatrix(pathMeasure.getLength() * mFloat, mMatrix,
         PathMeasure.POSITION_MATRIX_FLAG | PathMeasure.TANGENT_MATRIX_FLAG);
 //将图片的旋转坐标调整到图片中心位置
 mMatrix.preTranslate(-mBitmap.getWidth() / 2, -mBitmap.getHeight() / 2);
 canvas.drawPath(mPath, mPaint);
 canvas.drawBitmap(mBitmap,mMatrix, mPaint);

效果:

自定义控件神器--PathMeasure

源码地址


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

爆品手记

爆品手记

金错刀 / 中国友谊出版公司 / 2016-9-20 / 39.80

互联网时代,一切都被颠覆。 B2B、B2C、O2O等商业模式的建立,对传统企业构成了巨大冲击。人们的生意往来逐渐从线下转移到了线上,传统的定位理论逐渐失效,依靠爆品引爆市场才是王道;传统企业经营多年的渠道营销模式正遭遇前所未有的阻力,网上商城正成为众多商家角逐血拼的主要战场。 在互联网的黑暗森林里,一切传统的商业模式统统失效,一场依靠爆品点燃市场、引爆市场、占据市场的营销革命正悄然兴起......一起来看看 《爆品手记》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换