Path相关方法讲解(一)


上一篇主要讲了Canvas的translate(平移) 、scale(缩放) 、rotate(旋转) 、skew(错切),接下来几篇主要讲下android里的Path(封装了贝塞尔曲线)& Canvas里的drawPath(path,paint);

很多人听到贝塞尔曲线,就觉得似乎挺高端大气上档次,后面会和大家一起揭开它的面纱,一睹真容;

Path(路径):

我们先看看Path类里有哪些方法

Path相关方法讲解(一)_第1张图片

Path相关方法讲解(一)_第2张图片

咱们从上往下看:

构造函数有两个,分别是

    /**
     * Create an empty path
     */
    public Path() {
        mNativePath = init1();
        mDetectSimplePaths = HardwareRenderer.isAvailable();
    }

    /**
     * Create a new path, copying the contents from the src path.
     *
     * @param src The path to copy from when initializing the new path
     */
    public Path(Path src) {
        int valNative = 0;
        if (src != null) {
            valNative = src.mNativePath;
        }
        mNativePath = init2(valNative);
        mDetectSimplePaths = HardwareRenderer.isAvailable();
    }

这没啥好说的,第二种就是直接复用src 里设置的属性创建一个新的Path对象;

path.reset():清除掉path里的线条和曲线,但是不会改变它的fill-type(后面setFillType再说);

path.rewind():清除掉path里的线条和曲线,但是会保留内部的数据结构以便重用;

path.set(Path src);用src的内容替换原path的内容,一起看个小例子:

创建一个path,添加一个实心圆到path里

mEndPath = new Path();
mEndPath.addCircle(300, 300, 100, Direction.CW);
绘制该path:

canvas.drawPath(mEndPath, mPaint);
效果如下,无可厚非:

Path相关方法讲解(一)_第3张图片

此时在path里再添加一个矩形:

mEndPath = new Path();
mEndPath.addCircle(300, 300, 100, Direction.CW);
mEndPath.addRect(new RectF(50, 50, 250, 200), Direction.CW);
效果如下:

Path相关方法讲解(一)_第4张图片

做如下改动:

mEndPath = new Path();
mEndPath.addCircle(300, 300, 100, Direction.CW);
//mEndPath.addRect(new RectF(50, 50, 250, 200), Direction.CW);

mSrcPath = new Path();
mSrcPath.addRect(new RectF(50, 50, 250, 200), Direction.CW);
mEndPath.set(mSrcPath);
直接运行,如果在4.0以上的机器上(4.0及以上硬件加速默认开启),会发现屏幕上什么都没有了,说明该方法会受到硬件加速的影响,关掉硬件加速,再看效果:

Path相关方法讲解(一)_第5张图片

下面一起来看看Path 的 FillType - 填充模式:

android里定义了四种FillType,分别是:

 WINDING          (0),

 EVEN_ODD         (1),

 INVERSE_WINDING    (2),

 INVERSE_EVEN_ODD   (3)

有张图可以专门用来说明这四种模式的差别:

Path相关方法讲解(一)_第6张图片

以上图示已经非常清晰,我们还是用如下代码做下测试:

mEndPath = new Path();
mEndPath.addCircle(300, 300, 150, Direction.CW);
mEndPath.addCircle(380, 380, 150, Direction.CW);
mEndPath.setFillType(FillType.INVERSE_EVEN_ODD);

mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Style.FILL);
mPaint.setColor(Color.RED);
测试结果如下图:

Path相关方法讲解(一)_第7张图片

不设置FillType:

Path相关方法讲解(一)_第8张图片           Path相关方法讲解(一)_第9张图片

setFillType(FillType.WINDING)          setFillType(FillType.EVEN_ODD): 


Path相关方法讲解(一)_第10张图片           Path相关方法讲解(一)_第11张图片

setFillType(FillType.INVERSE_WINDING):   setFillType(FillType.INVERSE_EVEN_ODD):


根据以上图示,Path的FillType可以总结如下:

1.Path的默认FillType为 FillType.WINDING;

2.作用的范围为绘制 Path 的 Canvas 整体,而非 path 所在区域;

3.FillType.WINDING:取path所有所在区域;

4.FillType.EVEN_ODD:取path所在并不相交区域;

5.FillType.INVERSE_WINDING:取path所有未占区域;

6.FillType.INVERSE_EVEN_ODD:取path未占或相交区域;

下面看看和填充模式相关的几个方法:

getFillType():不用多说,返回 Path 的填充模式;

setFillType():设置 Path 的填充模式;

isInverseFillType():是否是 逆 填充模式:

WINDING 和 EVEN_ODD 返回false,INVERSE_WINDING 和 INVERSE_EVEN_ODD 返回true;

toggleInverseFillType():切换相反的填充模式,举个小例子:

        mEndPath = new Path();
        mEndPath.addCircle(300, 300, 150, Direction.CW);
        mEndPath.addCircle(380, 380, 150, Direction.CW);
        mEndPath.setFillType(FillType.WINDING);
        mEndPath.toggleInverseFillType();

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Style.FILL);
        mPaint.setColor(Color.RED);
此时给Path设置了WINDING的填充模式,调用toggleInverseFillType(),最终的模式为:

FillType.INVERSE_WINDING

Path相关方法讲解(一)_第12张图片

isEmpty():path是否为空,如果path不包含任何线条和曲线,则返回true,否则返回false;

isRect(RectF rect):如果path指定的是一个rect,则返回true,否则返回false,如果返回true & rect 不为null,则将该rect设置为path 的区域;

computeBounds(RectF bounds,boolean exact):计算path所在区域,并将结果写入bounds,如果整个path只包含0或1个点,将返回(0,0,0,0):

用如下代码做下测试:

        mComputeRect = new RectF();
        mEndPath = new Path();
        mEndPath.addCircle(380, 380, 150, Direction.CW);
        mEndPath.addRect(new RectF(200, 300, 500, 500), Direction.CW);
        mEndPath.computeBounds(mComputeRect, false);
        Toast.makeText(
                mContext,
                "" + mComputeRect.left + "," + mComputeRect.top + "," + mComputeRect.right + ","
                        + mComputeRect.bottom,
                Toast.LENGTH_LONG).show();

返回结果为(200,230,530,530),即path所含内容的边界区域

Path相关方法讲解(一)_第13张图片

incReserve(int extraPtCount):提示path将会增加extraPtCount个点,这能使path有效率的分配它的存储空间;


好了,这篇就主要介绍这些方法,后面主要介绍 Path 里 XXXTo 和 addXXX 相关的方法,最后我们再一起用Path做个例子!














你可能感兴趣的:(android动效篇)