PathMeasure 基本介绍

PathMeasure,顾名思义,就是一个用来测量Path的类,有以下方法:

image-20201215151755040

需要重点关注的有以下方法:

构造方法

  • 无参构造方法
public PathMeasure() {
    mPath = null;
    native_instance = native_create(0, false);
}

创建一个空的PathMeasure,使用之前需要先与创建好的 Path关联。如果关联之后 Path 内容进行了更改,则需要使用 setPath 方法重新关联。

  • 有参构造方法
public PathMeasure(Path path, boolean forceClosed) {
    // The native implementation does not copy the path, prevent it from being GC'd
    mPath = path;
    native_instance = native_create(path != null ? path.readOnlyNI() : 0, forceClosed);
}

创建一个 PathMeasure 并关联一个Path(已创建的),其中:

  • 参数path: 必须是之前已经创建好的,并且关联之后对Path内容进行了更改,则需要重新关联
  • 参数forceClosed:
    • 用来确保Path闭合,如果设置为 true, 则不论之前Path是否闭合,都会自动闭合该 Path(如果Path可以闭合的话)
    • forceClosed 不会影响原有Path的状态
    • forceClosed 的设置状态可能会影响测量结果,如果 Path 没有闭合但在与 PathMeasure 关联的时候设置 forceClosed 为 true 时,测量结果可能会比 Path 实际长度稍长一点,获取得到的是该 Path 闭合时的状态

getLenght()

用于获取Path的长度。

public float getLength() {
    return native_getLength(native_instance);
}

getMatrix()

获取路径上某一长度的位置以及该位置的正切值矩阵。

/**
* 获取路径上某一长度的位置以及该位置的正切值的矩阵
* @param distance 距离 Path 起点的长度,取值范围: 0 <= distance <= getLength
* @param matrix 根据 falgs的设置而封装的matrix
* @param flags 规定哪些内容会存入到matrix中,可选择:POSITION_MATRIX_FLAG(位置)、ANGENT_MATRIX_FLAG(正切)
* @return 判断获取是否成功,true表示成功,数据会存入matrix中,false 失败,matrix内容不会改变
*/
public boolean getMatrix(float distance, Matrix matrix, int flags) {
    return native_getMatrix(native_instance, distance, matrix.native_instance, flags);
}

getPosTan()

获取指定长度的位置坐标及该点切线值tangle。

/**
* 获取指定长度的位置坐标及该点切线值tangle
*
* @param distance 距离 Path 起点的长度,取值范围: 0 <= distance <= getLength
* @param pos 该点的坐标值,坐标值: (x==[0], y==[1])
* @param tan 该点的正切值,正切值: (x==[0], y==[1])
* @return 判断获取是否成功,true表示成功,数据会存入 pos 和 tan 中, false 表示失败,pos 和 tan 不会改变
*/
public boolean getPosTan(float distance, float pos[], float tan[]) {
    if (pos != null && pos.length < 2 ||
        tan != null && tan.length < 2) {
        throw new ArrayIndexOutOfBoundsException();
    }
    return native_getPosTan(native_instance, distance, pos, tan);
}

getSegment()

用于获取Path的一个片段。

/**
* 用于获取Path的一个片段
* @param startD 开始截取位置距离 Path 起点的长度 取值范围: 0 <= startD < stopD <= Path总长度
* @param stopD 结束截取位置距离 Path 起点的长度 取值范围: 0 <= startD < stopD <= Path总长度
* @param dst 截取的 Path 将会添加到 dst 中 注意: 是添加,而不是替换
* @param startWithMoveTo 起始点是否使用 moveTo,用于保证截取的 Path 第一个点位置不变
*/
public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) {
    // Skia used to enforce this as part of it's API, but has since relaxed that restriction
    // so to maintain consistency in our API we enforce the preconditions here.
    float length = getLength();
    if (startD < 0) {
        startD = 0;
    }
    if (stopD > length) {
        stopD = length;
    }
    if (startD >= stopD) {
        return false;
    }
 
    return native_getSegment(native_instance, startD, stopD, dst.mutateNI(), startWithMoveTo);
}

注意:

  • 如果 startD、stopD 的数值不在取值范围 [0, getLength] 内,或者 startD == stopD 则返回值为 false,不会改变 dst 内容。

  • 如果在安卓4.4或者之前的版本,在默认开启硬件加速的情况下,更改 dst 的内容后可能绘制会出现问题,请关闭硬件加速或者给 dst 添加一个单个操作,例如: dst.rLineTo(0, 0)

  • 可以用以下规则来判断 startWithMoveTo 的取值:

    true:保证截取得到的 Path 片段不会发生形变;

    false:保证存储截取片段的 Path(dst) 的连续性。

isClosed()

用于判断 Path 是否闭合,但是如果你在关联 Path 的时候设置 forceClosed 为 true 的话,这个方法的返回值则一定为true。

public boolean isClosed() {
    return native_isClosed(native_instance);
}

setPath()

关联一个预先创建好的Path。

public void setPath(Path path, boolean forceClosed) {
    mPath = path;
    native_setPath(native_instance,
                   path != null ? path.readOnlyNI() : 0,
                   forceClosed);
}

nextContour()

public boolean nextContour() {
    return native_nextContour(native_instance);
}

用于跳转到下一条曲线到方法,如果跳转成功,则返回 true, 如果跳转失败,则返回 false。 注意:使用多路径的效果需要关闭硬件加速。

PatherMeasure 使用

进度条

loading_view

源码地址: LoadingView.kt

箭头进度条

arrow_loading

源码地址: ArrowLoadingView.kt