android 自定义控件--Path 基本用法

Path 使用方法详解

此篇是看了一名来自2.5次元的魔法师的文章后做的笔记,原文http://www.gcssloop.com/customview/Path_Bezier,大家可以看下,文很棒

1. 第一组:moveTo、setLastPoint 、lineTo 、close

方法:lineTo

public void lineTo (float x, float y)

例:画两条线

 public PathView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        //初始化画笔
        mPaint = new Paint();             // 创建画笔
        mPaint.setColor(Color.BLACK);           // 画笔颜色 - 黑色
        mPaint.setStyle(Paint.Style.STROKE);    // 填充模式 - 描边
        mPaint.setStrokeWidth(10);              // 边框宽度 - 10

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        //获取宽高
        width = h;
        height = w;
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.translate(width / 2, height / 2);  // 移动坐标系到屏幕中心(宽高数据在onSizeChanged中获取)

        Path path = new Path();                     // 创建Path

        path.lineTo(200, 200);                      // lineTo 从默认点0,0到 200,200
        path.lineTo(200, 0);                        //再从200,200 到点 200,0

        canvas.drawPath(path, mPaint);              // 绘制Path
    }

结果如图,黑色线图像为结果,图中添加坐标系,有利于理解

这里写图片描述

Path 默认点是坐标原点0,0
事例代码中调用了两次lineTo,

第一次:path.lineTo(200, 200); //从0,0 到点A(200,200)的连线
第二次:path.lineTo(200, 0);//从A(200,200) 到点 B(200,0)的连线
方法 moveTo 和 setLstPoint
// moveTo
public void moveTo (float x, float y)

// setLastPoint
public void setLastPoint (float dx, float dy)
方法名简介是否影响之前操作是否影响之后操作
moveTo移动下一次操作的起点位置
setLastPoint设置之前操作的最后一个点位置

方法 moveTo

例:

canvas.translate(width / 2, height / 2);  // 移动坐标系到屏幕中心(宽高数据在onSizeChanged中获取)
Path path = new Path();                     // 创建Path
path.lineTo(200, 200);                      // lineTo 从默认点0,0到 200,200
path.moveTo(200, 100);                      // moveTo 改变下一个点开始的位置
path.lineTo(200, 0);                        // 由于moveTo改变了开始位置,所以从200,100 到点 200,0
canvas.drawPath(path, mPaint);              // 绘制Path

这里写图片描述

moveTo只改变下次操作的起点,在执行完第一次LineTo的时候,本来的默认点位置是A(200,200),但是moveTo将其改变成为了C(200,100),所以在第二次调用lineTo的时候就是连接C(200,100) 到 B(200,0) 之间的直线

方法setLstPoint

例:

canvas.translate(width / 2, height / 2);  // 移动坐标系到屏幕中心(宽高数据在onSizeChanged中获取)
        Path path = new Path();                     // 创建Path
        path.lineTo(200, 200);                      // lineTo 从默认点0,0到 200,200
//        path.moveTo(200, 100);                      // moveTo 改变下一个点开始的位置
        path.setLastPoint(200,100);                 // setLastPoint 改变上一个点结束的位置
        path.lineTo(200, 0);                        // 由于moveTo改变了开始位置,所以从200,100 到点 200,0
        canvas.drawPath(path, mPaint);              // 绘制Path

效果:
这里写图片描述

在执行完第一次的lineTo的时候,最后一个点是A(200,200),而setLastPoint更改最后一个点为B(200,200)为(200,100),所以在实际执行的时候,第一次的lineTo就不是从原点O到A(200,200)的连线了,而变成了从原点O到C(200,100)之间的连线了。

方法 close

public void close()

用于连接当前最后一个点和最初的点(如果两个点不重合),形成一个闭合的图形

结果:
这里写图片描述

2. 第二组:addXxx 与 arcTo

第一类(基本形状)

// 圆形
public void addCircle (float x, float y, float radius, Path.Direction dir)
// 椭圆
public void addOval (RectF oval, Path.Direction dir)
// 矩形
public void addRect (float left, float top, float right, float bottom, Path.Direction dir)
public void addRect (RectF rect, Path.Direction dir)
// 圆角矩形
public void addRoundRect (RectF rect, float[] radii, Path.Direction dir)
public void addRoundRect (RectF rect, float rx, float ry, Path.Direction dir)

最后一个参数都是Path.Direction,意思是方向,绘制时点是你是逆时针还是顺时针,在添加图形时确定闭合顺序(各个点的记录顺序)

类型含义
CW顺时针
CCW逆时针

例子:画一个矩形,顺时针

canvas.translate(width / 2, height / 2);  // 移动坐标系到屏幕中心
Path path = new Path();
path.addRect(-200, -200, 200, 200, Path.Direction.CW);//顺时针
canvas.drawPath(path, mPaint);

结果:
这里写图片描述

其实顺时针和逆时针的表面结果是一样的,只是过程不同,是怎么画成的

第二类方法(Path)

// path
public void addPath (Path src)
public void addPath (Path src, float dx, float dy)
public void addPath (Path src, Matrix matrix)

第一个方法:将两个Path合并成为一个

第二个方法比第一个方法多出来的两个参数是将src进行了位移之后再添加进当前path中。

第三个方法是将src添加到当前path之前先使用Matrix进行变换。

例子:

       canvas.translate(width / 2, height / 2);  // 移动坐标系到屏幕中心
        canvas.scale(1,-1);                         // <-- 注意 翻转y坐标轴

        Path path = new Path();
        Path src = new Path();

        path.addRect(-200,-200,200,200, Path.Direction.CW);//绘制一个矩形
        src.addCircle(0,0,100, Path.Direction.CW);//坐标原点绘制一个圆形

        path.addPath(src,0,200);//将圆形添加到矩形的上 0,200的位置

        canvas.drawPath(path,mPaint);

结果:
这里写图片描述

第三类方法(addArc与arcTo)

// addArc
public void addArc (RectF oval, float startAngle, float sweepAngle)
// arcTo
public void arcTo (RectF oval, float startAngle, float sweepAngle)
public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)

方法区别

名称作用区别
addArc添加一个圆弧到path直接添加一个圆弧到path中
arcTo添加一个圆弧到path添加一个圆弧到path,如果圆弧的起点和上次最后一个坐标点不相同,就连接两个点

参数含义

参数含义
oval圆弧的外切矩形
startAngle开始角度
sweepAngle扫过角度(-360 <= sweepAngle < 360)
forceMoveTo是否强制使用MoveTo

sweepAngle取值范围是 [-360, 360),不包括360,当 >= 360 或者 < -360 时将不会绘制任何内容, 对于360,你可以用一个接近的值替代,例如: 359.99

foreMoveTo含义等价方法
true将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点public void addArc (RectF oval, float startAngle, float sweepAngle)
false不移动,而是连接最后一个点与圆弧起点public void arcTo (RectF oval, float startAngle, float sweepAngle)

例子(addArc):

canvas.translate(width / 2, height / 2);  // 移动坐标系到屏幕中心
canvas.scale(1,-1);                       // <-- 注意 翻转y坐标轴
Path path = new Path();
path.lineTo(100,100);                       //先画个线

RectF oval = new RectF(0,0,300,300);        //确定圆弧的外切矩形的位置

path.addArc(oval,0,270);                    //在已有的线的基础上添加圆弧
 // path.arcTo(oval,0,270,true);             // <-- 和上面一句作用等价

 canvas.drawPath(path,mPaint);

结果:
这里写图片描述

例子(arcTo):

 canvas.translate(width / 2, height / 2);  // 移动坐标系到屏幕中心
 canvas.scale(1,-1);                         // <-- 注意 翻转y坐标轴

        Path path = new Path();
        path.lineTo(100,100);                       //先画个线

        RectF oval = new RectF(0,0,300,300);        //确定圆弧的外切矩形的位置

        path.arcTo(oval,0,270);                      //在已有的线的基础上添加圆弧,不移动,而是连接最后一个点与圆弧起点
        // path.arcTo(oval,0,270,false);             // <-- 和上面一句作用等价

        canvas.drawPath(path,mPaint);

结果:
这里写图片描述

3. isEmpty 、isRect、 isConvex、 set 、offset

方法: isEmpty

判断path中是否包含内容。

Path path = new Path();
Log.e("1",path.isEmpty()+"");

path.lineTo(100,100);
Log.e("2",path.isEmpty()+"");

结果:

com.sloop.canvas E/1: true
com.sloop.canvas E/2: false

方法:isRect

public boolean isRect (RectF rect)

判断path是否是一个矩形,如果是一个矩形的话,会将矩形的信息存放进参数rect中

path.lineTo(0,400);
path.lineTo(400,400);
path.lineTo(400,0);
path.lineTo(0,0);

RectF rect = new RectF();
boolean b = path.isRect(rect);
Log.e("Rect","isRect:"+b+"| left:"+rect.left+"| top:"+rect.top+"| right:"+rect.right+"| bottom:"+rect.bottom);

结果:

com.sloop.canvas E/Rect: isRect:true| left:0.0| top:0.0| right:400.0| bottom:400.0

方法:set

public void set (Path src)

将新的path赋值到现有path。

canvas.translate(mWidth / 2, mHeight / 2);  // 移动坐标系到屏幕中心
canvas.scale(1,-1);                         // <-- 注意 翻转y坐标轴

Path path = new Path();                     // path添加一个矩形
path.addRect(-200,-200,200,200, Path.Direction.CW);

Path src = new Path();                      // src添加一个圆
src.addCircle(0,0,100, Path.Direction.CW);

path.set(src);                              // 大致相当于 path = src;

canvas.drawPath(path,mPaint);

结果:
这里写图片描述

方法 offset

public void offset (float dx, float dy)
public void offset (float dx, float dy, Path dst)

对path进行一段平移,它和Canvas中的translate作用很像,但Canvas作用于整个画布,而path的offset只作用于当前path。

方法第最后的参数 Path dst 是存储平移后的path的

dst状态效果
dst不为null将当前path平移后的状态存入dst中,不会影响当前path
dat为空平移将作用于当前path,相当于第一种方法
// ====== 方法 offset ========
        canvas.translate(width/2 , height / 2);  // 移动坐标系到屏幕中心
        canvas.scale(1,-1);                         // <-- 注意 翻转y坐标轴

        Path path = new Path();                     // path中添加一个圆形(圆心在坐标原点)
        path.addCircle(0,0,100, Path.Direction.CW);

        Path dst = new Path();                      // dst中添加一个矩形
        dst.addRect(-200,-200,200,200, Path.Direction.CW);

        path.offset(250,0,dst);                     // 平移
        canvas.drawPath(path,mPaint);               // 绘制path
        mPaint.setColor(Color.BLUE);                // 更改画笔颜色
        canvas.drawPath(dst,mPaint);                // 绘制dst

结果:
平移之前:
这里写图片描述

平移后:
这里写图片描述

从运行效果图可以看出,虽然我们在dst中添加了一个矩形,但是并没有表现出来,所以,当dst中存在内容时,dst中原有的内容会被清空,而存放平移后的path。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值