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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章