Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義View之Path解析

Android自定義View之Path解析

編輯:關於Android編程

馬上要到五一了,提前祝賀大家五一快樂。

今天的主角是路勁,這個詞給我的第一印象就是那種彎彎的小路,屆時讓我想起了小時候的曲徑通幽處,反正我是忘記了下一句是什麼。言歸正傳,Android中的Path又有哪一些呢,以及它們的常用方法。

Path常用方法

方法 作用 備注 moveTo 移動起點 移動下一次操作的起點位置 lineTo 連接直線 連接上一個點到當前點之間的直線 setLastPoint 設置終點 重置最後一個點的位置 close 閉合路勁 從最後一個點連接最初的一個點,形成一個閉合區域 addRect 添加矩形 添加矩形到當前Path addRoundRect 添加圓角矩形 添加圓角矩形到當前Path addOval 添加橢圓 添加橢圓到當前Path addCircle 添加圓 添加圓到當前Path addPah 添加路勁 添加路勁到當前Path addArc 添加圓弧 添加圓弧到當前Path arcTo 圓弧 繪制圓弧,注意和addArc的區別 isEmpty 是否為空 判定Path是否為空 isRect 是否為矩形 判定Path是否是一個矩形 set 替換路勁 用新的路勁替換當前路勁的所有內容 offset 偏移路勁 對當前的路勁進行偏移 quadTo 貝塞爾曲線 二次貝塞爾曲線的方法 cubicTo 貝塞爾曲線 三次貝塞爾曲線的方法 rMoveTo,rlineTo,rQuadTo,rCubicTo rXxx方法 不帶r的方法是基於原點坐標系(偏移量),帶r的基於當前點坐標系(偏移量) op 布爾操作 對兩個Path進行布爾運算(交集,並集)等操作 setFillType 填充模式 設置Path的填充模式 getFillType 填充模式 獲取Path的填充 isInverseFillType 是否逆填充 判斷是否是逆填充模式 toggleInverseFillType 相反模式 切換相反的填充模式 getFillType 填充模式 獲取Path的填充 incReserve 提示方法 提示Path還有多少個點等待加入 computeBounds 計算邊界 計算Path的路勁 reset,rewind 重置路勁 清除Path中的內容(reset相當於new Path , rewind 會保留Path的數據結構) transform 矩陣操作 矩陣變換

Path方法使用詳解

使用Path不僅可以繪制簡單的圖形(如圓形,矩形,直線等),也可以繪制復雜一些的圖形(如正多邊形,五角星等),還有繪制裁剪和繪制文本都會用到Path。由於方法比較多,我這裡分組來講下。

moveTo , lineTo , setLastPoint , close

先創建畫筆:

        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10);
        paint.setColor(Color.parseColor("#FF0000"));

注意paint.setStyle(Paint.Style.FILL);,設置畫筆為實心。一些線條將在畫布上看不見。

1、lineTo

首先我們來看看lineTo,如果你直接moveTo 將看不出效果。

        Path path = new Path();

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

        canvas.drawPath(path,paint);

path

為了方便大家好觀察坐標的變化,我在屏幕上畫出了網格,每塊網格的寬高都是100。由於第一次之前沒有過操作,所以默認點就是原點(屏幕左上角),第一次lineTo就是坐標原點到(200,200)之間的直線。第二次lineTo就是上一次結束點位置(200,200)到(400,0)點之間的直線。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoNCBpZD0="2moveto-和setlastpoint">2、moveTo 和setLastPoint

方法預覽:

moveTo(float x, float y) 

setLastPoint(float dx, float dy)

這兩個方法在作用上有相似之處,卻是兩個不同的東西,具體參考下表:

方法名 作用 是否影響之前的操作 是否影響之後的操作 moveTo 移動下一次操作的起點位置 否 是 setLastPoint 改變上一次操作點的位置 是 是

來看看下面的例子:

        Path path = new Path();

        path.lineTo(200, 200);
        path.moveTo(300,300);
        path.lineTo(400, 0);

        canvas.drawPath(path, paint);

效果圖:

path

        Path path = new Path();

        path.lineTo(200, 200);
        path.setLastPoint(300,100);
        path.lineTo(400, 0);

        canvas.drawPath(path, paint);

效果圖:

path

當我們繪制線條之前,調用moveTosetLastPoint效果是一樣的,都是對坐標原點(0,0)進行操作。setLastPoint是重置上一次操作的最後一點,在執行完第一次lineTo的時候,最後一個點就是(200,200),setLastPoint更改(200,200)為(300,100),所以在執行的時候就是(300,100)到(400, 0)之間的連線了。

3、close

方法預覽

public void close()

close方法連接最後一個點和最初一個點(如果兩個點不重合)形成一個閉合的圖形。

        path.moveTo(100,100);
        path.lineTo(500,100);
        path.lineTo(300,400);
        path.close();
        canvas.drawPath(path, paint);

效果圖:

path

上圖中可以看到lineTo(500,100)直線和lineTo(300,400)直線,而close方法就是連接(300,400),(100,100)兩點,形成一個閉合的區域。

注意:close的作用的封閉路徑,如果連接最後一個點和最初一個點任然無法形成閉合的區域,那麼close什麼也不做。

quadTo,cubicTo

二次貝塞爾曲線以及三次貝塞爾曲線。

1、quadTo

方法預覽

public void quadTo(float x1, float y1, float x2, float y2)

quadTo方法其中 (x1,y1) 為控制點,(x2,y2)為結束點。

        path.moveTo(100,400);
        path.quadTo(300, 100, 400, 400);

        canvas.drawPath(path, paint);

效果圖:

path

2、cubicTo

方法預覽:

public void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)

cubicTo方法比quadTo方法多了一個點坐標,那麼其中(x1,y1) 為控制點,(x2,y2)為控制點,(x3,y3) 為結束點。

        path.moveTo(100, 400);
        path.cubicTo(100, 400, 300, 100, 400, 400);

        canvas.drawPath(path, paint);

繪制的圖形和上面的quadTo繪制的圖形是一樣的。我們去掉moveTo來看看運行的效果圖:

path

如果你想了解貝塞爾曲線公式,請鏈接這裡

addXxx和arcTo

主要是向Path中添加基本圖形以及區分addArcarcTo

1、添加基本圖形

方法預覽:

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

我們仔細觀察上面的方法,在最後都有一個Path.Direction,這是個什麼東東呢?Direction的意思是方向,指導,趨勢。點進去跟一下你會發現Direction是一個枚舉類型(Enum)分別有CW(順時針),CCW(逆時針)兩個常量。那麼它的作用主要有以下兩點:

序號 作用 1 在添加圖形時確定閉合順序(各個點的記錄順序) 2 對自相交圖形的渲染結果有影響

我們先來看看閉合順序的問題,添加一個矩形看看:

        path.addRect(100, 200, 500, 400, Path.Direction.CW);

        canvas.drawPath(path, paint);

path

我將上面的代碼CW改成CCW再運行一次,結果一模一樣,尼瑪區別在哪裡啊。稍安勿躁,想看到區別就要用到setLastPoint(重置最後一個點的坐標)。我們來這樣變變代碼:

        path.addRect(100, 200, 500, 400, Path.Direction.CW);
        path.setLastPoint(200,400);

        canvas.drawPath(path, paint);

效果立馬現行:

path

為什麼圖形會發生奇怪的變化呢。我們先來分析一下,繪制一個矩形至少需要對角線的兩個點,根據這兩個點計算出四條邊然後把四條邊按照順序連接起來。上圖的起始坐標是(100,200)按著順時針的方向連接(500,200),(500,400),(100,400)最後連接(100,200)形成一個矩形。setLastPoint是重置上一個操作點坐標及改變(100,400)為(200,400),所以出現了上圖的效果。

接下來我們看看逆時針的情況:

        path.addRect(100, 200, 500, 400, Path.Direction.CCW);
        path.setLastPoint(400,300);

        canvas.drawPath(path, paint);

效果圖:

path

我們理清楚了閉合的問題,相交問題與設置填充模式有關。

我以addCircle方法來講解添加圖形,並不會逐一講解。

        path.addCircle(300,300,200, Path.Direction.CW);

        canvas.drawPath(path, paint);

path

繪制圓形,(300,300)點表示圓心坐標,200 表示半徑長度。

2、addPath

方法預覽:

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

addPath方法就是將兩個路徑合並到一起。第二個方法的dx,dy指的是偏移量,第三個方法是添加到當前path之前先使用Matrix進行變換。來看看下面例子:

        Path path = new Path();
        path.addRect(100,100,400,300, Path.Direction.CW);

        Path src=new Path();
        src.addCircle(300,300,100, Path.Direction.CW);
        path.addPath(src,0,100);

        canvas.drawPath(path, paint);

效果圖:

path

3、addArc與arcTo

方法預覽:

addArc(RectF oval, float startAngle, float sweepAngle)
addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)

arcTo(RectF oval, float startAngle, float sweepAngle)
arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)

從方法名字上面看,這兩個方法都是與圓弧有關,那麼他們之間肯定是有區別的:

名稱 作用 區別 addArc 添加一個圓弧到Path 直接添加一個圓弧到path中,和上一次操作點無關 arcTo 添加一個圓弧到Path 添加一個圓弧到path中,如果圓弧的起點和上次操作點坐標不同就連接兩個點

startAngle表示開始圓弧度數(0度與X軸方向對齊,順時針移動,弧度增大)。

注意:sweepAngle表示運動了多少弧度,並不是結束弧度。

forceMoveTo表示“是否強制使用moveTo”,也就是說是否使用moveTo將上一次操作點移動到圓弧的起點坐標。默認是false。

forceMoveTo 含義 true 將最後一個點移動到圓弧起點,即不連接最後一個點與圓弧起點 false 不移動,而是連接最後一個點與圓弧起點(注意之前沒有操作的話,不會連接原點)

示例:

        path.lineTo(200, 200);
        RectF rectF = new RectF(100, 100, 400, 400);
        path.arcTo(rectF, 0, 270, true);
        // path.addArc(rectF,0,270);和上面一句等價

        canvas.drawPath(path, paint);

效果圖:

path

我們把 path.arcTo(rectF, 0, 270, true);改成 path.arcTo(rectF, 0, 270, false);,來看看效果圖:

path

從上面兩張圖可以看出明顯的變化。

isEmpty、 isRect、 set 和 offset

isEmpty

判斷path中是否包含內容。

        Path path = new Path();
        Log.e("-----","----"+path.isEmpty());//-----: ----true
        path.lineTo(100,100);
        Log.e("-----","----"+path.isEmpty());//-----: ----false

        canvas.drawPath(path, paint);

isRect

方法預覽:

isRect(RectF rect)

判斷path是否是一個矩形,如果是一個矩形的話,會將矩形的信息存放進參數rect中。

        Path path = new Path();
        RectF rectF = new RectF();
        rectF.left = 100;
        rectF.top = 100;
        rectF.right = 400;
        rectF.bottom = 300;
        path.addRect(rectF, Path.Direction.CW);
        boolean isRect = path.isRect(rectF);
        Log.e("-----","------"+isRect);//-----: ------true

set

方法預覽:

public void set(Path src)

將新的path賦值到現有path。相當於運算符中的“=”,如a=b,把b賦值給a

還是一起來看個例子:

        Path path = new Path();
        path.addRect(100,100,400,300, Path.Direction.CW);
        Path src=new Path();
        src.addCircle(300,200,100, Path.Direction.CW);
        path.set(src);
        canvas.drawPath(path, paint);

效果圖:

path

offset

方法預覽:

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

這個方法就是對Path進行一段平移,正方向和X軸,Y軸方向一致(如果dx為正數則向右平移,反之向左平移;如果dy為正則向下平移,反之向上平移)。我們看到第二個方法多了一個dst,這個又是一個什麼玩意呢,其實參數das是存儲平移後的path的。

用例子來說明一下:

        Path path = new Path();
        path.addCircle(300, 200, 100, Path.Direction.CW);

        Path dst = new Path();
        dst.addCircle(500, 200, 200, Path.Direction.CW);

        path.offset(-100, 100, dst);
        canvas.drawPath(path, paint);

效果圖:

path

從運行效果圖可以看出,雖然我們在dst中添加了一個圓形,但是並沒有表現出來,所以,當dst中存在內容時,dst中原有的內容會被清空,而存放平移後的path。

FillType

方法預覽:

public void setFillType(Path.FillType ft)
public Path.FillType getFillType()

setFillType方法中的參數Path.FillType為枚舉類型:

FillType值 含義 FillType.WINDING 取path所有所在區域 默認值 FillType.EVEN_ODD 取path所在並不相交區域 FillType.INVERSE_WINDING 取path所有未占區域 FillType.INVERSE_EVEN_ODD 取path未占或相交區域

path所在區域
path所在區域
path所在區域

setFillType

WINDING

        Path path = new Path();
        path.addCircle(300,200,100, Path.Direction.CW);
        path.addCircle(200,200,100, Path.Direction.CW);
        path.setFillType(Path.FillType.WINDING);
        canvas.drawPath(path, paint);

效果圖:

path

EVEN_ODD

代碼我就不貼了,直接上圖(上mis):

path

INVERSE_WINDING

path

INVERSE_EVEN_ODD

path

isInverseFillType

是否是逆填充模式:WINDING 和 EVEN_ODD 返回false;
INVERSE_WINDING 和 INVERSE_EVEN_ODD 返回true;

toggleInverseFillType

切換相反的填充模式,如果填充模式為WINDING則填充模式為INVERSE_WINDING,反之為WINDING模式;如果填充模式為EVEN_ODD則填充模式為INVERSE_EVEN_ODD,反之為EVEN_ODD模式。

舉個例子:

        Path path = new Path();
        path.addCircle(300,200,100, Path.Direction.CW);
        path.addCircle(200,200,100, Path.Direction.CW);
        path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
        path.toggleInverseFillType();
        canvas.drawPath(path, paint);

效果圖和上面EVEN_ODD模式一模一樣。

path

就寫到這裡,文中有什麼寫錯,寫偏的請給我留言。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved