1. 程式人生 > >Android中Path類的使用

Android中Path類的使用

Path是android中用來封裝幾何學路徑的一個類,因為Path在圖形繪製上佔的比重還是相當大的。你可以用它來繪製各種樣式的幾何圖形,做圖表什麼的都可以。

一、畫線段

1.1 lineT(float x, float y)

先來看一段程式碼:

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeWidth(
5); // 例項化路徑 mPath = new Path(); // 連線路徑到點[100,100] mPath.lineTo(100, 100); // 繪製路徑 canvas.drawPath(mPath, mPaint); }
複製程式碼

效果就是將起始點和(100,100)進行連線。這裡因為沒有設定起始點,所以預設是canvas的左上角,而這裡預設的canvas和螢幕重合,所以就成了這個樣子。

當然我們可以考慮多次呼叫lineTo方法來繪製更復雜的圖形:

複製程式碼
    @Override
    protected
void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(5); // 例項化路徑 mPath = new Path(); mPath.moveTo(100, 100); // 連線路徑到點 mPath.lineTo(300, 100); mPath.lineTo(
400, 200); mPath.lineTo(200, 200); // 繪製路徑 canvas.drawPath(mPath, mPaint); }
複製程式碼

1.2 moveTo(float x, float y)  

我們可以通過moveTo(float x, float y) 來移動起始的座標點,比如:

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeWidth(5);
        
        // 例項化路徑
        mPath = new Path();
        //移動點至[300,300]  
        mPath.moveTo(300, 300);  
        // 連線路徑到點[100,100]
        mPath.lineTo(100, 100);
        // 繪製路徑
        canvas.drawPath(mPath, mPaint);
    }
複製程式碼

1.3 close()

上面的例子我們構建了一個類似平行四邊形的影象,如果此時我們想閉合該曲線讓它變成一個形狀該怎麼做呢?聰明的你一定想到:

mPath.lineTo(100, 100)  

然而Path給我提供了更便捷的方法:

close()

在上面的例子新增close()後就會自動構建一條末點和起始點的線段:

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeWidth(5);
        
        // 例項化路徑
        mPath = new Path();
        mPath.moveTo(100, 100);  
        // 連線路徑到點  
        mPath.lineTo(300, 100);  
        mPath.lineTo(400, 200);  
        mPath.lineTo(200, 200); 
        // 閉合曲線
        mPath.close();
        // 繪製路徑
        canvas.drawPath(mPath, mPaint);
    }
複製程式碼

二、畫貝賽爾曲線

2.1 貝賽爾曲線

什麼叫貝賽爾曲線?其實很簡單,使用三個或多個點來確定的一條曲線,貝塞爾曲線在圖形影象學中有相當重要的地位,Path中也提供了一些方法來給我們模擬低階貝賽爾曲線。

貝塞爾曲線的定義也比較簡單,你只需要一個起點、一個終點和至少零個控制點則可定義一個貝賽爾曲線,當控制點為零時,只有起點和終點,此時的曲線說白了就是一條線段,我們稱之為一階貝賽爾曲線。

PS:以下圖片和公式均來自維基百科和網際網路

一階貝賽爾曲線:

其公式可概括為:

其中B(t)為時間為t時點的座標,P0為起點、Pn為終點

貝塞爾曲線於1962年由法國數學家Pierre Bézier第一次研究使用並給出了詳細的計算公式,So該曲線也是由其名字命名。Path中給出的quadTo方法屬於

二階貝賽爾曲線:

二階貝賽爾曲線的一個明顯特徵是其擁有一個控制點,大家可以這樣想想貝賽爾曲線,在一根兩端固定橡皮筋上有一塊磁鐵,現在我們拿另一塊磁鐵去吸引橡皮筋上的磁鐵,因為引力,橡皮筋會隨著我們手上磁鐵的移動而改變形狀,又因為橡皮筋的張力讓束縛在橡皮筋上的磁鐵不會輕易吸附到我們手上的磁鐵,這時橡皮筋的狀態就可以看成是一條貝塞爾曲線,而我們手中的磁鐵就是一個控制點,通過這個控制點我們“拉扯”橡皮筋的曲度。

二階貝賽爾曲線的公式為:

同樣的,Path中也提供了三階貝塞爾曲線的方法cubicTo,按照上面我們的推論,三階應該是有兩個控制點才對對吧

三階貝賽爾曲線:

公式:

高階貝賽爾曲線在Path中沒有對應的方法,對我們來說三階也足夠了,不過大家可以瞭解下,難得我在牆外找到如此動感的貝賽爾曲線高清無碼動圖

高階貝塞爾曲線:

四階:

五階:

貝塞爾曲線通用公式:

2.2 quadTo(float x1, float y1, float x2, float y2)

上面說了一階的就是一條線段,所以直接來看二階。下面的方法可以讓我們繪製“二階”貝賽爾曲線

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

解釋:其中quadTo的前兩個引數為控制點的座標,後兩個引數為終點座標,至於起點預設是畫布的左上角。這裡的p0就是起點,(x1,y1)就是中點P1,(x2,y2)就是末端點P2。

現在,我們使用它來繪製一條曲線:

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeWidth(5);
        
        // 例項化路徑
        mPath = new Path();
        // 移動起點至[100,100]  
        mPath.moveTo(100, 100);  
          
        // 連線路徑到點  
        mPath.quadTo(200, 200, 300, 100); 
        canvas.drawPath(mPath, mPaint);
    }
複製程式碼

效果:

 示意圖: 

2.3 cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)  

它可以繪製三階貝賽爾曲線

與quadTo類似,前四個引數表示兩個控制點,最後兩個引數表示終點。其實,(x1,y1)就是P1,(x2,y2)是P2,(x3,y3)是P3。

下面用程式碼來繪製一下:

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeWidth(5);
        
        // 例項化路徑
        mPath = new Path();
        // 移動起點至[100,100]  
        mPath.moveTo(100, 100);  
          
        // 連線路徑到點  
        mPath.cubicTo(200, 200, 300, 0, 400, 100);  
        canvas.drawPath(mPath, mPaint);
    }
複製程式碼

  示意圖: 

三、畫弧線

arcTo (RectF oval, float startAngle, float sweepAngle)  

是一個畫弧線的方法,其實說白了就是從圓或橢圓上擷取一部分而已。

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeWidth(5);
        
        // 例項化路徑
        mPath = new Path();
        // 移動起點至[100,100]  
        mPath.moveTo(100, 100);  
        // 連線路徑到點  
        RectF oval = new RectF(100, 100, 200, 200);  
        mPath.arcTo(oval, 0, 90); 
        canvas.drawPath(mPath, mPaint);
    }
複製程式碼

上面的程式碼首先構建出一個矩形區域,這個區域內就是橢圓和園的區域,橢圓或園會內切於這個矩形區域。然後我們設定圓弧的其實角度和最終角度來擷取圓弧。

注意:使用Path生成的路徑必定都是連貫的,雖然我們使用arcTo繪製的是一段弧但其最終都會與我們的起始點[100,100]連線。

如果你不想連怎麼辦?Path也提供了另一個過載方法:

arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)  

它會強制起點為繪製的起始點,而不是畫布的左上角。我們來看看效果:

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeWidth(5);
        
        // 例項化路徑
        mPath = new Path();
        // 移動起點至[100,100]  
        mPath.moveTo(100, 100);  
        // 連線路徑到點  
        RectF oval = new RectF(100, 100, 200, 200);  
        mPath.arcTo(oval, 0, 90,true); 
        canvas.drawPath(mPath, mPaint);
    }
複製程式碼

四、rXXXTo方法

Path中除了上面介紹的幾個XXXTo方法外還有一套rXXXTo方法:

rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)  
rLineTo(float dx, float dy)  
rMoveTo(float dx, float dy)  
rQuadTo(float dx1, float dy1, float dx2, float dy2)  

這一系列rXXXTo方法其實跟上面的那些XXXTo差不多的,唯一的不同是rXXXTo方法的參考座標是相對的而XXXTo方法的參考座標始終是參照畫布原點座標,什麼意思呢?舉個簡單的例子:

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeWidth(5);
        
        // 例項化路徑
        mPath = new Path();
        // 移動點至[100,100]  
        mPath.moveTo(100, 100);  
  
        // 連線路徑到點  
        mPath.lineTo(200, 200); 
        canvas.drawPath(mPath, mPaint);
    }
複製程式碼

這裡的move和lineTo的座標都是對於畫布左上角(0,0)來說的,是一個絕對座標。而我們換為mPath.rLineTo(200, 200); 後呢?

是不是感覺線段長了很多,因為這裡的(200,200)是相對於開始點(100,100)來說的,是相對座標。如果換算成絕對座標就是繪製一條(100,100)到(300,300)之間的線段。其實,這個字首“r”也就是relative(相對)的簡寫!

五、addXXX方法

XXXTo方法可以連線Path中的曲線而Path提供的另一系列addXXX方法則可以讓我們直接往Path中新增一些曲線,比如

addArc(RectF oval, float startAngle, float sweepAngle)  

它允許我們將一段弧形新增至Path,注意這裡我用到了“新增”這個詞彙,也就是說,通過addXXX方法新增到Path中的曲線是不會和上一次的曲線進行連線的:

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(5);

        // 例項化路徑
        mPath = new Path();
        // 移動點至[100,100]
        mPath.moveTo(100, 100);

        // 連線路徑到點
        mPath.lineTo(200, 200);
        // 新增一條弧線到Path中
        RectF oval = new RectF(100, 100, 300, 400);
        mPath.addArc(oval, 0, 90);

        canvas.drawPath(mPath, mPaint);
    }
複製程式碼

如圖和程式碼所示,雖然我們先繪製了由[100,100]到[200,200]的線段,但是在我們往Path中添加了一條弧線後該弧線並沒與線段連線。

除了addArc,Path還提供了一系列的add方法:

addCircle(float x, float y, float radius, Path.Direction dir)  
addOval(float left, float top, float right, float bottom, Path.Direction dir)  
addRect(float left, float top, float right, float bottom, Path.Direction dir)  
addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir)  

這些方法和addArc有很明顯的區別,就是多了一個Path.Direction引數,其他呢都大同小異,除此之外不知道大家還發現沒有,addArc是往Path中新增一段弧,說白了就是一條開放的曲線,而上述幾種方法都是一個具體的圖形,或者說是一條閉合的曲線,Path.Direction的意思就是標識這些閉合曲線的閉合方向。Path.Direction只有兩個常量值CCWCW分別表示逆時針方向閉合和順時針方向閉合。

那什麼叫閉合方向呢?光說大家一定會蒙,有學習激情的童鞋看到後肯定會馬上敲程式碼試驗一下兩者的區別,可是不管你如何改,單獨地在一條閉合曲線上你是看不出所謂閉合方向的區別的。為了弄懂它,我們在path上繪製一些文字來說明最後引數的意義:

複製程式碼
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);

        // 例項化路徑
        mPath = new Path();
        // 移動起點至[100,100]
        mPath.moveTo(100, 100);

        // 新增一條弧線到Path中  
        RectF oval = new RectF(100, 100, 300, 400);  
        mPath.addOval(oval, Path.Direction.CW); 

        canvas.drawPath(mPath, mPaint);
        
        mPaint.setTextSize(50);
        // 繪製路徑上的文字  
        canvas.drawTextOnPath("123456789", mPath, 0, 0, mPaint); 
    }
複製程式碼

如果我們換作:

mPath.addOval(oval, Path.Direction.CCW); 

繪製的文字全都沿著Path跑到閉合曲線的“內部”了。

相關推薦

AndroidPath的lineTo方法和quadTo方法畫線的區別

   當我們需要在螢幕上形成畫線時,Path類的應用是必不可少的,而Path類的lineTo和quadTo方法實現的繪製線路形式也是不一樣的,下面就以程式碼的實現來直觀的探究這兩個方法的功能實現區別;    1. Path--->quadTo(float x1, fl

AndroidPath的使用

Path是android中用來封裝幾何學路徑的一個類,因為Path在圖形繪製上佔的比重還是相當大的。你可以用它來繪製各種樣式的幾何圖形,做圖表什麼的都可以。 一、畫線段 1.1 lineT(float x, float y) 先來看一段程式碼: @Override protec

androidLog的封裝

col mark pre class 打印日誌 static sta 日誌 blog 1.為了方便的使用Log打印日誌,以及後續方便撤銷日誌打印,所以對Log類進行封裝是一件好事。 1 package market.phone; 2 3 import androi

AndroidCalendar的用法總結

jsb ews 寫法 需要 key data- minute bar 來講 Calendar是Android開發中需要獲取時間時必不可少的一個工具類,通過這個類可以獲得的時間信息還是很豐富的,下面做一個總結,以後使用的時候就不用總是去翻書或者查資料了。 在獲取時間之前要先獲

C#Path的簡單實用

      在進行檔案操作的時候,獲得檔案路徑,目錄等一些列常用的方法,C#中的Path這個類都對其進行了簡單封裝,只需要直接呼叫方法實用就可以了。       Path    path   =&

AndroidApplication總結

application類的使用   要使用自定義的Application,首先就是要自己新建一個Application的子類,然後把它的名字寫在manifest檔案裡面的application標籤裡的android:name屬性就行,如我的Application子類名字

Swift-->R.swift帶你體驗AndroidR的便利

安裝需要2點: 1:需要執行一段指令碼 "$PODS_ROOT/R.swift/rswift" "$SRCROOT" 2:指令碼生成的檔案R.generated.swift,需要複製到專案中, 這樣才能愉快的使用R.swift 使

Android同步Mutex(AutoMutex)與Condition。

 在Android中,封裝的同步類主要有Mutex(AutoMutex)與Condition。 這兩個類在android中被大量的使用,這也說明這兩個類是非常重要的。 下面我們就從3個方面來分析他們。 它們是什麼,他們的實現原理,即what 為什麼要這

.NETPath的幾個方法(轉載)

來源:新浪部落格  給大家介紹幾個.NET中Path類的幾個方法:  1. Path.combine(string, string)  根據給出的兩個路徑, 返回一個路徑.  例如: string CompletePath = System.IO.Path.Combine(@"c:/MyApp",

AndroidApplication儲存全域性變數

在Android應用中使用全域性變數,除了public的靜態變數,還有更優雅的方式是使用android.app.Application。 啟動Application時,系統會建立一個PID,即程序ID,所有的Activity就會在此程序上執行。 那麼我們在A

AndroidBuildConfig的那些事

宣告 本文章都只是在AndroidStudio基於Gradle構建專案開發的驗證,所以不保證其它開發環境與構建專案方式也是這樣 BuildConfig身在何處 瞭解一個東西前,至少先要知道這東西在哪裡吧!而我們今天要了解的這個類又在哪裡了,我相信應該還

AndroidLayoutInflater的inflate方法的使用及注意事項

轉自:http://www.ithao123.cn/content-10951307.html [摘要:我們正在講一個界說好的結構檔案(xml)檔案減載到界裡上揭示出去的時間,平常會用到LayoutInflater的inflate方式,仔細的同硯會發明那個方式有四種過載,

AndroidHandler的簡單使用,實現圖片切換

Handler類主要有兩個作用:在新啟動的執行緒中傳送訊息。在主執行緒中獲取、處理訊息。當新啟動的執行緒傳送訊息時,Handler類中處理訊息的方法會被自動回撥。Handler類包含如下方法用於傳送、處理訊息: 下面通過一個簡單例項來演示Handler的使用,實現點選切

AndroidApplication用法(整個程式的全域性變數,即單例),類似於session

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.test"

Android .stub的使用

stub類是為了方便client,service互動而生成出來的程式碼。 AIDL(Android Interface Definition Language Android介面定義語言)實現程序間通訊,尤其是在涉及多程序併發情況下的程序間通訊 aidl會在gen中自動生

淺析AndroidParcel

在淺析繫結遠端服務bindService基本原理與AIDL分析中,我們在使用服務呼叫遠端服務的函式時,到底可以傳遞哪些型別的引數類,在AIDL程序間傳遞複雜資料型別中,我們詳細解析了它可以傳遞的資料型別,那麼到底為什麼它只能傳遞這些資料型別。 其實我們在呼叫遠

Android Rect

Rect位於android.graphics下,表示一個矩形,由四條邊的座標組成,提供了一些設定方法,都比較簡單,原始碼如下: /* * Copyright (C) 2006 The Android Open Source Project * * Licensed u

android支持多種文件型的下載

context nts 下載 tor oid tracking ref pen art String directoryName = Environment.getExternalStorageDirectory().toString()

Android 圖能夠用到的圖片處理 BitmapUtils

andro radius title can rup decode eww row 上下 Android在實際開發中非常多時候都要對圖片進行一定的處理,這裏總結的BitmapUtils 類包含一下幾個功能: 1.Android圖片倒影, 2.Android圖片模糊處理,

C# 基礎知識-07----.NETDirectory 和Path 和 Environment

cto directory .com -- mage rec alt 基礎 path C# 基礎知識-07----.NET中Directory 和Path 類 和 Environment類