進階畫布繪圖
我們已經介紹了Canvas,在那裡,已經學習了如何建立自己的View。在第7章中也使用了Canvas來為MapView標註覆蓋。
畫布(Canvas)是圖形編程中一個很普通的概念,通常由三個基本的繪圖組件組成:
Canvas 提供了繪圖方法,可以向底層的位元影像繪製基本圖形。
Paint 也稱為"刷子",Paint可以指定如何將基本圖形繪製到位元影像上。
Bitmap 繪圖的表面。
Android繪圖API支援透明度、漸層填充、圓邊矩形和消除鋸齒。遺憾的是,由於資源限制,它還不支援向量圖形,它使用的是傳統光柵樣式的重新繪圖。
這種光柵方法的結果是提高了效率,但是改變一個Paint對象不會影響已經畫好的基本圖形,它只會影響新的元素。
提示:
如果你擁有Windows開發背景,那麼Android的2D繪圖能力大致相當於GDI+的能力。
1. 可以畫什嗎?
Canvas類封裝了用作繪圖表面的位元影像;它還提供了draw*方法來實現設計。
下面的列表提供了對可用的基本圖形的簡要說明,但並沒有深入地探討每一個draw方法的詳細內容:
drawARGB / drawRGB / drawColor 使用單一的顏色填充畫布。
drawArc 在一個矩形地區的兩個角之間繪製一個弧。
drawBitmap 在畫布上繪製一個位元影像。可以通過指定目標大小或者使用一個矩陣來改變目標位元影像的外觀。
drawBitmapMesh 使用一個mesh(網)來繪製一個位元影像,它可以通過移動網中的點來操作目標的外觀。
drawCircle 以給定的點為圓心,繪製一個指定半徑的圓。
drawLine(s) 在兩個點之間畫一條(多條)直線。
drawOval 以指定的矩形為邊界,畫一個橢圓。
drawPaint 使用指定的Paint填充整個Canvas
drawPath 繪製指定的Path。Path對象經常用來儲存一個對象中基本圖形的集合。
drawPicture 在指定的矩形中繪製一個Picture對象。
drawPosText 繪製指定了每一個字元的位移量的文本字串。
drawRect 繪製一個矩形。
drawRoundRect 繪製一個圓角矩形。
drawText 在Canvas上繪製一個文本串。文本的字型、大小和渲染屬性都設定在用來渲染文本的Paint對象中。
drawTextOnPath 在一個指定的path上繪製文本。
drawVertices 繪製一系列三角形面片,通過一系列頂點來指定它們。
這些繪圖方法中的每一個都需要指定一個Paint對象來渲染它。在下面的部分中,將學習如何建立和修改Paint對象,從而在繪圖中完成大部分工作。
2. 從Paint中完成工作
Paint類相當於一個筆刷和調色盤。它可以選擇如何使用上面描述的draw方法來渲染繪製在畫布上的基本圖形。通過修改Paint對象,可以在繪圖的時候控制顏色、樣式、字型和特殊效果。最簡單地,setColor可以讓你選擇一個Paint的顏色,而Paint對象的樣式(使用setStyle控制)則可以決定是繪製繪圖對象的輪廓(STROKE),還是只填充每一部分(FILL),或者是兩者都做(STROKE_AND_FILL)
除了這些簡單的控制之外,Paint類還支援透明度,另外,它也可以通過使用各種各樣的陰影、過濾器和效果進行修改,從而提供由更豐富的、複雜的畫筆和顏料組成的調色盤。
Android SDK包含了一些非常好的執行個體,它們說明了Paint類中可用的大部分功能。你可以在API demos的graphics子目錄中找到它們:
sdk root folder]\samples\ApiDemos\src\com\android\samples\graphics
在下面的部分中,將學習和使用其中的部分功能。這些部分只是簡單地羅列了它們能實現的效果(例如漸層和邊緣浮雕),而沒有詳細地列出所有可能的情況。
使用透明度
Android中的所有顏色都包含了一個不透明組件(alpha通道)。
當建立一個顏色的時候,可以使用argb或者parseColor方法來定義它的alpha值,如下所示:
Java代碼:
- // 使用紅色,並讓它50%透明
- int opacity = 127;
- int intColor = Color.argb(opacity, 255, 0, 0);
- int parsedColor = Color.parseColor("#7FFF0000");
複製代碼
或者,也可以使用setAlpha方法來設定已存在的Paint對象的透明度:
Java代碼:
- // 讓顏色50%透明
- int opacity = 127;
- myPaint.setAlpha(opacity);
複製代碼
建立一個不是100%透明的顏色意味著,使用它繪製的任何基本圖形都將是部分透明的--也就是說,在它下面繪製的所有基本圖形都是部分可見的。
可以在任何使用了顏色的類或者方法中使用透明效果,包括Paint、Shader和Mask Filter。
Shader介紹
Shader類的衍生類別可以建立允許使用多種固體顏色填充繪圖對象的Paint。
對Shader最常見的使用是定義漸層填充;漸層是在2D映像中添加深度和紋理的最佳方式之一。Android包含了一個Bitmap Shader和一個Compose Shader,同時,還包含了三個漸層的Shader。
試圖用語言來描述繪圖的效果本來就是沒有意義的,所以看一就應該可以知道每一種Shader是如何工作的。圖中從左至右依次代表的是LinearGradient、RadialGradient和 SweepGradient.
提示:
沒有包含的是ComposerShader,它可以建立多個Shader和BitmapShader的組合,從而可以在一個位元影像映像的基礎上建立一個繪圖刷。
要在繪圖的時候使用一個Shader,可以使用setShader方法將其應用到一個Paint中,如下面的代碼所示:
Paint shaderPaint = new Paint();
shaderPaint.setShader(myLinearGradient);
你使用這個Paint所繪製的任何東西都將使用你指定的Shader進行填充,而不是使用Paint本身的顏色進行填充。
定義漸層Shader
如上所示,使用漸層Shader可以讓你使用交替改變的顏色來填充圖片;你可以將色彩坡形定義為兩種顏色的簡單交替,如下所示:
java代碼:
- int colorFrom = Color.BLACK;
- int colorTo = Color.WHITE;
- LinearGradient linearGradientShader = new LinearGradient(x1, y1, x2, y2, colorFrom, colorTo, TileMode.CLAMP);
複製代碼
或者,你還可以定義更複雜的按照設定比例進行分布的顏色序列,如下面的RadialGradientShader例子所示:
java代碼:
- int[] gradientColors = new int[3];
- gradientColors[0] = Color.GREEN;
- gradientColors[1] = Color.YELLOW;
- gradientColors[2] = Color.RED;
- float[] gradientPositions = new float[3];
- gradientPositions[0] = 0.0f;
- gradientPositions[1] = 0.5f;
- gradientPositions[2] = 1.0f;
- RadialGradient radialGradientShader=new RadialGradient(centerX,centerY, radius, gradientColors, gradientPositions, TileMode.CLAMP);
複製代碼
每一種漸層Shader(線性、輻射形的和掃描狀的)都可以使用以上這兩種技術來定義漸層填充。
使用Shader TileModes
漸層Shader的畫刷大小既可以顯式地使用有邊界的矩形來定義,也可以使用中心點和半徑長度來定義。Bitmap Shader可以通過它的位元影像大小來決定它的畫刷大小。