Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android資訊 >> Android繪圖之Path總結

Android繪圖之Path總結

編輯:Android資訊

Path作為Android中一種相對復雜的繪圖方式,官方文檔中的有些解釋並不是很好理解,這裡作一個相對全面一些的總結,供日後查看,也分享給大家,共同進步。

1.基本繪圖方法

  1. addArc(RectF oval, float startAngle, float sweepAngle)
    繪制弧線,配合Paint的Style可以實現不同的填充效果
  2. addCircle(float x, float y, float radius, Path.Direction dir)
    繪制圓形,其中第dir參數用來指定繪制時是順時針還是逆時針
  3. addOval(RectF oval, Path.Direction dir)
    繪制橢圓形,其中 oval作為橢圓的外切矩形區域
  4. addRect(RectF rect, Path.Direction dir)
    繪制矩形
  5. addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)
    繪制圓角矩形
  6. lineTo(float x, float y)
    繪制直線
  7. addPath(Path src)
    添加一個新的Path到當前Path
  8. arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
    addArc方法相似,但也有區別,下文細述。
  9. quadTo(float x1, float y1, float x2, float y2)
    繪制二次貝塞爾曲線,其中 (x1,y1)為控制點,(x2,y2)為終點
  10. cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
    繪制三次貝塞爾曲線,其中(x1,y1),(x2,y2)為控制點,(x3,y3)為終點

2.rXXX方法

上面的lineTo,MoveTo,QuadTo,CubicTo方法都有與之對應的rXXX方法:

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

這些方法與之對應的原方法相比,惟一的區別在於:r方法是基於當前繪制開始點的offest,比如當前paint位於 (100,100)處,則使用rLineTo(100,100)方法繪制出來的直線是從(100,100)到(200,200)的一條直接,由此可見rXXX方法方便用來基於之前的繪制作連續繪制。

3.Path.op方法

//原型
op(Path path, Path.Op op)
//eg
path1.op(path2,Path.Op.DIFFERENCE);

此方法用於對兩個Path對象做相應的運算組合(combine),具體的說是根據不同的op參數及path2參數來影響path1對象,有點類似於數學上的集合運算。請看下面的例子:

Path path1 = new Path();
path1.addCircle(150, 150, 100, Path.Direction.CW);
Path path2 = new Path();
path2.addCircle(200, 200, 100, Path.Direction.CW);
path1.op(path2, Path.Op.DIFFERENCE);
canvas.drawPath(path1, paint1);

效果如下:

通過不斷修改path1.op的第二個參數依次可以得到如下效果:

Path.Op.INTERSECT效果:

Path.Op.UNION效果:

Path.Op.REVERSE_DIFFERENCE效果:

Path.Op.XOR效果:

總結:

  1. Path.Op.DIFFERENCE 減去path1中path1與path2都存在的部分;
    path1 = (path1 – path1 ∩ path2)
  2. Path.Op.INTERSECT 保留path1與path2共同的部分;
    path1 = path1 ∩ path2
  3. Path.Op.UNION 取path1與path2的並集;
    path1 = path1 ∪ path2
  4. Path.Op.REVERSE_DIFFERENCE 與DIFFERENCE剛好相反;
    path1 = path2 – (path1 ∩ path2)
  5. Path.Op.XOR 與INTERSECT剛好相反;
    path1 = (path1 ∪ path2) – (path1 ∩ path2)

4.setFillType

設置path的填充模式.網上關於path的FillType的介紹很少,實際上在官方ApiDemos裡就有個很好的例子:

/**
 * Created by ghui on 10/25/15.
 */
public class PathFillTypeView extends View {
	private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
	private Path mPath;

	public PathFillTypeView(Context context) {
		super(context);
		setFocusable(true);
		setFocusableInTouchMode(true);

		mPath = new Path();
		mPath.addCircle(40, 40, 45, Path.Direction.CCW);
		mPath.addCircle(80, 80, 45, Path.Direction.CCW);
		mPath.addCircle(120, 120, 45, Path.Direction.CCW);
	}

	private void showPath(Canvas canvas, int x, int y, Path.FillType ft,
						  Paint paint) {
		canvas.save();
		canvas.translate(x, y);
		canvas.clipRect(0, 0, 160, 160);
		canvas.drawColor(Color.WHITE);
		mPath.setFillType(ft);
		canvas.drawPath(mPath, paint);
		canvas.restore();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		Paint paint = mPaint;
		paint.setColor(Color.RED);
		canvas.drawColor(0xFFCCCCCC);
		canvas.translate(20, 20);
		paint.setAntiAlias(true);
		showPath(canvas, 0, 0, Path.FillType.WINDING, paint);
		showPath(canvas, 160 * 2, 0, Path.FillType.EVEN_ODD, paint);
		showPath(canvas, 0, 160 * 2, Path.FillType.INVERSE_WINDING, paint);
		showPath(canvas, 160 * 2, 160 * 2, Path.FillType.INVERSE_EVEN_ODD, paint);
	}
}

效果如下:


(上面的例子在官方ApiDemo的基礎上做了適當的修改)

總結:

所謂填充指的就是填充內部,setFillType就是用來界定哪裡算內部的算法。在計算機圖形學中界定一個點是不是在多邊形內部有兩種算法:

  1. 非零環繞數規則(Nonzero-rule)
  2. 奇偶規則(Even–odd rule)

關於這兩種算法這裡不作詳細介紹。

5.易混淆的方法

1. addArc 與 arcTo

前者指定在某處畫一條弧線,僅此而已,不會受當前paint的位置所影響。而arcTo方法有兩種形式:

  1. arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
  2. arcTo(RectF oval, float startAngle, float sweepAngle)對於第一種形式的方法,若forceMoveTo參數為false,則與第二種形式的方法沒區別,繪制成的最終圖形會受到落筆點的影響;
    若forceMoveTo參數值為true,則繪制效果與addArc方法沒有區別。
//代碼1
Path path = new Path();
path.moveTo(100, 100);
path.addArc(200, 200, 400, 400, 0, 150);
canvas.drawPath(path, paint);

代碼1效果如下圖:

//代碼2
Path path = new Path();
path.moveTo(100, 100);
path.arcTo(200, 200, 400, 400, 0, 150, false);
canvas.drawPath(path,paint);

代碼2效果如下圖:

若將代碼2中的arcTo方法的參數修改為true則繪制的效果與代碼1相同。

2. reset 與 rewind

reset清除path上的內容,重置path到 path = new Path()的初始狀態。
rewind清除path上的內容,但會保留path上相關的數據結構,以高效的復用。

其它方法

  1. moveTo(float x,float y)
    移動畫筆到 (x,y) 處
  2. offset(float dx, float dy)
    平移當前path,在此path上繪制的任何圖形都會受到影響
  3. close()
    閉合當前路徑 (系統會自動從起點到終點繪制一條直線,使當前路徑閉合)
  4. reset()
    重置path,但不會重置fill-type設置
  5. rewind()
    重置path,但會保留內部數據結構
  6. set(Path src)
    設置新的Path到當前對象
  7. setLastPoint(float x,float y)
    設置當前path的終點
  8. transform(Matrix matrix)
    矩陣變換
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved