1. 程式人生 > >Canvas畫各種圖形及控制元件在螢幕中的座標-android

Canvas畫各種圖形及控制元件在螢幕中的座標-android

我們已經介紹了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程式碼:
  1.     // 使用紅色,並讓它50%透明
  2.     int opacity = 127;
  3.     int intColor = Color.argb(opacity, 255, 0, 0);
  4.     int parsedColor = Color.parseColor("#7FFF0000");
複製程式碼 或者,也可以使用setAlpha方法來設定已存在的Paint物件的透明度:

Java程式碼:
  1.     // 讓顏色50%透明
  2.     int opacity = 127;
  3.     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程式碼:
  1.     int colorFrom = Color.BLACK;
  2.     int colorTo = Color.WHITE;
  3.     LinearGradient linearGradientShader = new LinearGradient(x1, y1, x2, y2, colorFrom, colorTo, TileMode.CLAMP);
複製程式碼
或者,你還可以定義更復雜的按照設定比例進行分佈的顏色序列,如下面的RadialGradientShader例子所示:

java程式碼:
  1.     int[] gradientColors = new int[3];
  2.     gradientColors[0] = Color.GREEN;
  3.     gradientColors[1] = Color.YELLOW;
  4.     gradientColors[2] = Color.RED;
  5.     float[] gradientPositions = new float[3];
  6.     gradientPositions[0] = 0.0f;
  7.     gradientPositions[1] = 0.5f;
  8.     gradientPositions[2] = 1.0f;
  9.     RadialGradient radialGradientShader=new RadialGradient(centerX,centerY, radius, gradientColors, gradientPositions, TileMode.CLAMP);
複製程式碼
 每一種漸變Shader(線性的、輻射形的和掃描狀的)都可以使用以上這兩種技術來定義漸變填充。


使用Shader TileModes
 漸變Shader的畫刷大小既可以顯式地使用有邊界的矩形來定義,也可以使用中心點和半徑長度來定義。Bitmap Shader可以通過它的點陣圖大小來決定它的畫刷大小。

如果Shader畫刷所定義的區域比要填充的區域小,那麼TileMode將會決定如何處理剩餘的區域:
CLAMP 使用Shader的邊界顏色來填充剩餘的空間。
MIRROR 在水平和垂直方向上拉伸Shader影象,這樣每一個影象就都能與上一個縫合了。
REPEAT 在水平和垂直方向上重複Shader影象,但不拉伸它。


使用MaskFilter

MaskFilter類可以為Paint分配邊緣效果。
對MaskFilter的擴充套件可以對一個Paint邊緣的alpha通道應用轉換。Android包含了下面幾種MaskFilter:

BlurMaskFilter 指定了一個模糊的樣式和半徑來處理Paint的邊緣。
EmbossMaskFilter 指定了光源的方向和環境光強度來新增浮雕效果。

要應用一個MaskFilter,可以使用setMaskFilter方法,並傳遞給它一個MaskFilter物件。下面的例子是對一個已經存在的Paint應用一個EmbossMaskFilter:

java程式碼:
  1.     // 設定光源的方向
  2.     float[] direction = new float[]{ 1, 1, 1 };
  3.     //設定環境光亮度
  4.     float light = 0.4f;
  5.     // 選擇要應用的反射等級
  6.     float specular = 6;
  7.     // 向mask應用一定級別的模糊
  8.     float blur = 3.5f;
  9.     EmbossMaskFilter emboss=new EmbossMaskFilter(direction,light,specular,blur);
  10.     // 應用mask myPaint.setMaskFilter(emboss);
複製程式碼


       SDK中包含的FingerPaint API demo是說明如何使用MaskFilter的一個非常好的例子。它展示了這兩種filter的效果。

      
使用ColorFilter

        MaskFilter是對一個Paint的alpha通道的轉換,而ColorFilter則是對每一個RGB通道應用轉換。所有由ColorFilter所派生的類在執行它們的轉換時,都會忽略alpha通道。

        
Android包含三個ColorFilter:


        ColorMatrixColorFilter  可以指定一個4×5的ColorMatrix並將其應用到一個Paint中。ColorMatrixes通常在程式中用於對影象進行處理,而且由於它們支援使用矩陣相乘的方法來執行連結轉換,所以它們很有用。

         LightingColorFilter  乘以第一個顏色的RGB通道,然後加上第二個顏色。每一次轉換的結果都限制在0到255之間。
         PorterDuffColorFilter  可以使用數字影象合成的16條Porter-Duff 規則中的任意一條來向Paint應用一個指定的顏色。

        使用setColorFilter方法應用ColorFilter,如下所示:
        myPaint.setColorFilter(new LightingColorFilter(Color.BLUE, Color.RED));

         API中的ColorMatrixSample是說明如何使用ColorFilter和Color Matrix的非常好的例子。

         使用PathEffect

         到目前為止,所有的效應都會影響到Paint填充影象的方式;PathEffect是用來控制繪製輪廓(線條)的方式。
PathEffect對於繪製Path基本圖形特別有用,但是它們也可以應用到任何Paint中從而影響線條繪製的方式。

         使用PathEffect,可以改變一個形狀的邊角的外觀並且控制輪廓的外表。Android包含了多個PathEffect,包括:
         CornerPathEffect  可以使用圓角來代替尖銳的角從而對基本圖形的形狀尖銳的邊角進行平滑。

DashPathEffect  可以使用DashPathEffect來建立一個虛線的輪廓(短橫線/小圓點),而不是使用實線。你還可以指定任意的虛/實線段的重複模式。

       DiscretePathEffect  與DashPathEffect相似,但是添加了隨機性。當繪製它的時候,需要指定每一段的長度和與原始路徑的偏離度。

       PathDashPathEffect  這種效果可以定義一個新的形狀(路徑)並將其用作原始路徑的輪廓標記。
       下面的效果可以在一個Paint中組合使用多個Path Effect。

       SumPathEffect  順序地在一條路徑中新增兩種效果,這樣每一種效果都可以應用到原始路徑中,而且兩種結果可以結合起來。

       ComposePathEffect  將兩種效果組合起來應用,先使用第一種效果,然後在這種效果的基礎上應用第二種效果。
       物件形狀的PathEffect的改變會影響到形狀的區域。這就能夠保證應用到相同形狀的填充效果將會繪製到新的邊界中。

       使用setPathEffect方法可以把PathEffect應用到Paint物件中,如下所示:

java程式碼:

  1.     borderPaint.setPathEffect(new CornerPathEffect(5));
複製程式碼


       PathEffect API示例給出瞭如何應用每一種效果的指導說明。

      
修改Xfermode

       可以通過修改Paint的Xfermode來影響在Canvas已有的影象上面繪製新的顏色的方式。
       在正常的情況下,在已有的影象上繪圖將會在其上面新增一層新的形狀。如果新的Paint是完全不透明的,那麼它將完全遮擋住下面的Paint;如果它是部分透明的,那麼它將會被染上下面的顏色。

       下面的Xfermode子類可以改變這種行為:
       AvoidXfermode  指定了一個顏色和容差,強制Paint避免在它上面繪圖(或者只在它上面繪圖)。
       PixelXorXfermode  當覆蓋已有的顏色時,應用一個簡單的畫素XOR操作。
       PorterDuffXfermode  這是一個非常強大的轉換模式,使用它,可以使用影象合成的16條Porter-Duff規則的任意一條來控制Paint如何與已有的Canvas影象進行互動。

       要應用轉換模式,可以使用setXferMode方法,如下所示:

java程式碼:

  1.     AvoidXfermode avoid = new AvoidXfermode(Color.BLUE, 10, AvoidXfermode.Mode. AVOID); borderPen.setXfermode(avoid);
複製程式碼


      
3. 使用抗鋸齒效果提高Paint質量

       在繪製一個新的Paint物件時,可以通過傳遞給它一些標記來影響它被渲染的方式。ANTI_ALIAS_FLAG是其中一種很有趣的標記,它可以保證在繪製斜線的時候使用抗鋸齒效果來平滑該斜線的外觀。

       在繪製文字的時候,抗鋸齒效果尤為重要,因為經過抗鋸齒效果處理之後的文字非常容易閱讀。要建立更加平滑的文字效果,可以應用SUBPIXEL_TEXT_FLAG,它將會應用子畫素抗鋸齒效果。

       也可以手工地使用setSubpixelText和setAntiAlias方法來設定這些標記,如下所示:

java程式碼:

  1.     myPaint.setSubpixelText(true);
  2.     myPaint.setAntiAlias(true);
複製程式碼


      
2D圖形的硬體加速

       在當前這個到處都是2D圖形愛好者的時代,Android允許你使用硬體加速來渲染你的應用程式。

       如果裝置可以使用硬體加速,那麼通過設定這個標記可以讓活動中的每一個View都能使用硬體渲染。儘管減少了系統處理程式的負載,但在極大地提高了影象處理速度的同時,硬體加速也帶來了相應的負面效果。

       使用requestWindowFeature方法,可以在你的活動中應用Window.FEATURE_OPENGL標記來開啟硬體加速,如下所示:

java程式碼:

  1.     myActivity.requestWindowFeature(Window.FEATURE_OPENGL);
複製程式碼


       並不是Android中所有的2D繪圖基本圖形都被硬體支援(特別是前面描述的大部分PathEffect)。

       與此同時,由於整個活動實際上是作為一個Canvas進行渲染的,所以對任何View的無效請求都將會導致整個活動被重新繪製。

      
Canvas繪圖最佳實踐經驗


       2D自繪操作是非常耗費處理程式資源的;低效的繪圖方法會阻塞GUI執行緒,並且會對應用程式的響應造成不利的影響。對於那些只有一個處理程式的資源受限的環境來說,這一點就更加現實了。

       這裡需要注意onDraw方法的資源消耗以及CPU週期的耗費,這樣才能保證不會把一個看起來很吸引人的應用程式變得完全沒有響應。

        目前有很多技術可以幫助將與自繪控制元件相關的資源消耗最小化。我們關心的不是一般的原則,而是某些Android特定的注意事項,從而保證你可以建立外觀時尚、而且能夠保持互動的活動(注意,以下這個列表並不完整):

       考慮硬體加速  OpenGL硬體加速對2D圖形的支援是非常好的,所以你總是應該考慮它是否適合你的活動。另一種比較優秀的方法是隻用一個單獨的View和迅速的、耗時的更新來組成活動。一定要保證你使用的基本圖形能夠被硬體支援。

       考慮大小和方向  當在設計View和佈局的時候,一定要保證考慮(和測試)它們在不同的解析度和大小下的外觀。

       只建立一次靜態物件  在Android中物件的建立是相當昂貴的。因此,在可能的地方,應用只建立一次像Paint物件、Path和Shader這樣的繪圖物件,而不是在View每次無效的時候都重新建立它們。

       記住onDraw是很消耗資源的  執行onDraw方法是很消耗資源的處理,它會強制Android執行多個圖片組合和點陣圖構建操作。下面有幾點建議可以讓你修改Canvas的外觀,而不用重新繪製它:

       使用Canvas轉換  可以使用像rotate和translate這樣的轉換,來簡化Canvas中元素複雜的相關位置。例如,相比放置和旋轉一個錶盤周圍的每一個文字元素,你可以簡單地將canvas旋轉22.5?,然後在相同的位置繪製文字。

       使用動畫  可以考慮使用動畫來執行View的預設定的轉換,而不是手動地重新繪製它。在活動的View中可以執行縮放、旋轉和轉換動畫,並可以提供一種能夠有效利用資源的方式來提供縮放、旋轉或者抖動效果。

       考慮使用點陣圖和9 Patch  如果View使用了靜態背景,那麼你應該考慮使用一個圖片,如點陣圖或者9 patch,而不是手動地重新繪製。

高階指南針錶盤的例子

       已經建立了一個簡單的指南針。而在上一章,你又回到了這個例子,對它進行了擴充套件從而使它夠使用加速計硬體來顯示橫向和縱向方向。

       那些例子中的UI都很簡單,從而保證了那些章節中的程式碼都儘可能地清晰。

       在下面的例子中,將對CompassView的onDraw方法做一些重要的改動,從而把它從一個簡單的、平面的指南針,變成一個動態的航空地平儀(artificial horizon ),如圖所示。

相關推薦

Canvas各種圖形控制元件螢幕座標-android

我們已經介紹了Canvas,在那裡,已經學習瞭如何建立自己的View。在第7章中也使用了Canvas來為MapView標註覆蓋。  畫布(Canvas)是圖形程式設計中一個很普通的概念,通常由三個基本的繪圖元件組成: Canvas  提供了繪圖方法,可以向底層的點陣圖繪製基本圖形。     

Android利用canvas各種圖形 Paint用法

Class Overview The Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the

Android利用canvas各種圖形(點、直線、弧、圓、橢圓、文字、矩形、多邊形、曲線、圓角矩形)

DrawView.java public class DrawView extends View { public DrawView(Context context) { super(context); } @Override protected void onDraw(Canvas c

Android 利用canvas各種圖形(點、直線、弧、圓、橢圓、文字、矩形、多邊形、曲線、圓角矩形)

1、首先說一下canvas類: Class Overview The Canvas class holds the “draw” calls. To draw something, you need 4 basic components: A Bitmap

表單控制元件

表單及控制元件 1、常用屬性 action,指定提交的地址 method,指定提交的方式,一般為get或post get方式請求:1、直接輸入地址訪問。2、表單沒有設定method時或設的為get,都是get方式的請求。get方式請求會將請求引數的名和

放肆的使用UIBezierPath和CAShapeLayer各種圖形

CAShapeLayer 是 CALayer 的子類,但是比 CALayer 更靈活,可以畫出各種圖形,當然,你也可以使用其他方式來畫,隨你。 雜談 在 CAShapeLayer 中,也可以像 CALayer 一樣指定它的 frame 來畫,就像這樣: let layer = CASha

ASP.net頁面控制元件

ASP.NET 是一個使用 HTML、CSS、JavaScript 和伺服器指令碼建立網頁和網站的開發框架。 ASP.NET 支援三種不同的開發模式: Web Pages(Web 頁面)、MVC(Model View Controller 模型-檢視-控制器)

註解學習之初始化佈局控制元件2

/** * @author anqiansong *初始化佈局 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface InitContentView { public int

放肆地用 UIBezierPath 和 CAShapeLayer 各種圖形

CAShapeLayer 是 CALayer 的子類,但是比 CALayer 更靈活,可以畫出各種圖形,當然,你也可以使用其他方式來畫,隨你。 雜談 在 CAShapeLayer 中,也可以像 CALayer 一樣指定它的 frame 來畫,就像這樣:

MFC學習之 對話方塊設定背景顏色控制元件透明的方法

對話方塊設定背景色之後控制元件不透明的問題。 1.對話方塊設定背景色: 方法1:(用OnPaint()) 在Dlg.h中:宣告 afx_msg void OnPaint();                                HICON m_hIcon; 在Dl

UML各種圖形作用

物件圖所使用的表示符號與類圖幾乎完全相同,它們的不同點在於物件圖只是顯示類的物件例項,而不是實際的類。一個物件圖是類圖的一個例項,由於物件存在生命週期,因此物件圖只能在系統某一時間段存在。 物件圖是類圖的一種例項化圖,描述系統在某個時刻可能包含的物件和相互關係。 (adsbyg

Monkeyrunner學習之任意節點控制元件獲取獲取對應控制元件的相對座標實現對控制元件的操作

最初我是用device.touch(button_x,button_y,'')的方法來實現對終端介面的操作,使用過程中發現這種方式可移植性很差,便發現了使用控制元件ID的方式來操作,我通過下面這2篇文章學習到如何獲取任意節點控制元件以及獲取其相對座標進行操作 原文:http

React Native佈局實踐:開發京東客戶端首頁(四)——首頁功能按鈕控制元件封裝

從我寫第一篇React Native文章以來,我們幾乎是把所有的程式碼都放在一個js檔案中實現的,隨著工程複雜度的增加,各種自定義控制元件的程式碼就和業務邏輯程式碼耦合嚴重,這篇文章就來解決這一問題,讓我們一起來學習控制元件封裝的方法。1.明確需求首頁功能按鈕由一個圖片、一行

MFC----視窗的縮放控制元件隨拖動改變大小

當我們想得到一個視窗物件(CWnd的派生物件)指標的控制代碼(HWND)時,最安全的方法是使用GetSafeHwnd()函式,通過下面的例子來看其理由:   CWnd *pwnd = FindWindow(“ExploreWClass”,NULL); //希望找到資源管理器   HWND hwnd = pwn

初識android——佈局控制元件

  趁著有空,連著發兩篇,是我前兩天看視訊學過的內容,不大體上發發,我怕我遺忘了。   言歸正傳,這次主要是佈局,因為一開始總用的LinearLayout,略顯粗糙,這次看的包括了相對佈局RelativeLayout,以及LinearLayout的巢狀佈局。控制元件部分了解

使用canvas不規則圖形

       最近做專案遇到一個需求,首頁介面採取斜切風格,開始拿到這個問題的時候考慮過幾種方案。一是用svg來解決不規則圖形的問題,但是貌似這種東西對於我們來說屬於嵌入式開發了比較麻煩,二是用CSS3提供的新屬性方法transform來解決問題,transform提供了三

Cocos-Lua UI控制元件

-----------------------------LayerColor--------------------------------local layer = cc.LayerColor:create(cc.c4b(0, 0, 0, 180))layer:addChild(layer)-------

快遞鳥批量列印電子面單介面控制元件安裝

目前支援批量列印電子面單的有快遞鳥、菜鳥和快遞公司。但是快遞公司僅能列印本公司的電子面單,對於電商等發貨商來說不太適用,菜鳥教適合淘系商家,快遞鳥則比較通用,這裡介紹快遞鳥電子面單介面批量列印的方法 對接流程: 快遞鳥網站申請介面KEY-對接介面-除錯-上線使用 介面支

VC++對話方塊(CDialog)的全屏顯示控制元件居中顯示

在編寫一些軟體時,我們會比較偏向於比較簡潔、清新的使用者介面,同時為了避免其它程式或者桌面等影響使用者的注意力等,我們通常習慣將軟體介面全屏,佈滿整個顯示螢幕,與此同時,我們也將對介面中的控制元件位置進行相應的調整,讓它們按螢幕的大小和其在對話方塊中的相對位置,居中顯示。

MFC修改對話方塊控制元件背景顏色

HBRUSH CMyDlg::OnCtlColor(CDC* pDC,CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr =CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes o