Andriod中繪(畫)圖----Canvas的使用詳解


   轉載請注明出處:http://blog.csdn.net/qinjuning    

 

 

            由於在網絡上找到關於Canvas的使用都比較抽象,也許是我的邏輯思維不太好吧,總是感覺理解起來比較困難,

    尤其是對save()和restore()方法的使用。本篇文章的內容就是對Canvas的使用進行一下總結,包括它的兩種不同的使用

    情節和它的一些方法進行一下說明。 

  

       1  Bitmap,可以來自資源/文件,也可以在程序中創建,實際上的功能相當於圖片的存儲空間;

       2  Canvas,緊密與Bitmap聯系,把Bitmap比喻內容的話,那么Canvas就是提供了眾多方法操作Bitamp的平台;

       3  Paint,與Canvas緊密聯系,是"畫板"上的筆刷工具,也用於設置View控件上的樣式;

       4  Drawable,如果說前三者是看不見地在內存中畫圖(虛擬的),那么Drawable就是把前三者繪圖結果表現出來的接口(真實的)。

              Drawable多個子類,例如:位圖(BitmapDrawable)、圖形(ShapeDrawable)、圖層(LayerDrawable)等。

   

      以上引自於hellogv的Android入門第十四篇之畫圖》

 

    我們打個簡單的比方吧:

                Paint        就是畫筆

                Bitmap    就是畫布

                Canvas   就是畫家

 

     於是,畫家可以通過畫筆可以在畫布上進行任何的畫畫。

 

Canvas的兩種使用情形,從Canvas對象的獲得角度分析:

 

    1、  自定義View和自定義SurfaceView中獲得Canvas對象

       由於自定義View和SurfaceView在顯示界面中已經獲得了顯示區域,canvas對象只不過是在其顯示(繪畫)區域進行界面布局

  的設計,當操作完畢后,系統會顯示canvas的操作結果。

 

       自定義View的繪圖方法為:

  1. 1 //存在canvas對象,即存在默認的顯示區域  
    2     @Override  
    3     public void draw(Canvas canvas) {  
    4          //canvas繪圖  
    5         }  

     


      SurfaceView的繪圖方法為,例如:

1 SurfaceView  surfaceView = new MySurfaceView() ;         //創建一個Surface對象  
2 SurfaceHolder surfaceHolder = surfaceView. getHolder() ;  //獲得SurfaceHolder對象  
3 Canvas   canvas  = surfaceHolder.lockCanvas() ;          //獲得canvas對象  
4 //進行繪圖操作  
5 surfaceHolder.unlockCanvasAndPost(canvas) ;            //釋放canvas鎖,並且顯示視圖  

 

 

    2、  在其他情形下,我們需要通過代碼創建一個Canvas對象,並且在繪畫成功后,將該畫圖區域轉換為Drawable圖片

  或者通過setBitmap(bitmap)顯現出來。一般步驟為: 

  1.  1 //創建一個的Bitmap對象   
     2   
     3    Bitmap bitmap = Bitmap.createBitmap(200, 100, Config.ARGB_8888) ;  
     4   //創建一個canvas對象,並且開始繪圖  
     5    Canvas canvas = new Canvas (bitmap) ;  
     6   
     7   ImageView imgView  = new ImageView(this) ;  //或者其他可以設置背景圖片的View控件  
     8    
     9   
    10    //為ImageView設置圖像  
    11    //將Bitmap對象轉換為Drawable圖像資  
    12    Drawable drawable = new BitmapDrawable(bitmap) ;  
    13   imgView .setBackgroundDrawable(drawable) ;  
    14   
    15   
    16   或者簡單點:  imgView  .setImageBitmap(bitmap);     

     

     這兩種方式都可以顯示我們的繪圖。
 

 Canvas方法分析:

 

         clipXXX()方法族

           說明:在當前的畫圖區域裁剪(clip)出一個新的畫圖區域,這個畫圖區域就是canvas對象的當前畫圖區域了。

              例如:clipRect(new Rect()),那么該矩形區域就是canvas的當前畫圖區域了。

        public int save()

           說明:保存已經由canvas繪畫出來的東西,在save()和restore()方法之間的操作不對它們造成影響,例如旋轉(roate)等。

               而且對canvas的操作(roate和translate)都是臨時的,restore()后不再存在。

       public voidrestore()

           說明:復原sava()方法之前保存的東西資源。

       drawXXX()方法族

           說明:以一定的坐標值在當前畫圖區域畫圖。

           注意:圖層會疊加,即后面繪畫的圖層會覆蓋前面繪畫的圖層。

 

 需要注意的方法是:

     public voiddrawRect(float left, float top, float right, float bottom,Paint paint)

           說明:繪制一個矩型。需要注明的是繪制矩形的參數和Java中的方法不一樣。

              該方法的參數圖解說明如下:

 

        各位看官請注意:圖中X、Y軸方向標記錯誤。 自己也懶得重新修正了。

 

           

           那么,矩形的高 height = bottom  - right 

                      矩形的寬 width  = right – left

 

       PS :假如drawRect的參數有誤,比如right < left ,Android是不會給我們檢查的,也不會提示相應的錯誤信息,

           但它會繪畫出一個高或寬很小的矩形,可能不是你希望的。

  

      public voidtranslate(float dx, float dy)

          說明:在當前的坐標上平移(x,y)個像素單位

                    若dx <0 ,沿x軸向上平移; dx >0  沿x軸向下平移

                    若dy <0 ,沿y軸向上平移; dy >0  沿y軸向下平移

     public void rotate(float degrees)

          說明:旋轉一定的角度繪制圖像。

         

         PS :從截圖上看,圖像是確實旋轉了,但是我找不到旋轉的依據中心。

 

下面給出該Demo的截圖,可以更改一些參數后自己觀察效果。

 

 

  1、布局文件 main.xkl :  采用了兩個ImageView來顯示bitmap繪圖對象, 讓后采用了一個自定義View繪圖

 
  1.  1 <?xml version="1.0" encoding="utf-8"?>  
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
     3     android:orientation="vertical" android:layout_width="fill_parent"  
     4     android:layout_height="fill_parent">  
     5   
     6     <View android:layout_width="fill_parent" android:layout_height="2dip" android:background="#800080" android:layout_marginTop="2dip"></View>  
     7     <TextView android:layout_width="fill_parent"  
     8         android:layout_height="wrap_content" android:text="<strong>顯示canvas區域以及clip方法的使用"</strong> />  
     9   
    10     <ImageView android:id="@+id/imgClip" android:layout_width="fill_parent"  
    11         android:layout_height="wrap_content" android:layout_marginTop="10dip" />  
    12   
    13     <View android:layout_width="fill_parent" android:layout_height="2dip" android:background="#800080" android:layout_marginTop="2dip"></View>  
    14     <TextView android:layout_width="fill_parent"  
    15         android:layout_height="wrap_content" android:text="<strong>save方法和restore方法的使用"</strong> />  
    16     <ImageView android:id="@+id/imgSave" android:layout_width="fill_parent"  
    17         android:layout_height="wrap_content" android:layout_marginTop="10dip" />  
    18   
    19     <View android:layout_width="fill_parent" android:layout_height="2dip" android:background="#800080" android:layout_marginTop="2dip"></View>  
    20     <TextView android:layout_width="fill_parent"  
    21         android:layout_height="wrap_content" android:text="<strong>自定義View,獲得了一個Canvas對象和繪圖區域</strong>" />  
    22     <com.qin.canvas.MyView android:id="@+id/myView"  
    23         android:layout_width="fill_parent" android:layout_height="200px" />  
    24   
    25 </LinearLayout>  

     


    2、自定義View  , MyView.java,

 
  1.  1 import android.content.Context;  
     2 import android.graphics.Bitmap;  
     3 import android.graphics.BitmapFactory;  
     4 import android.graphics.Canvas;  
     5 import android.graphics.Color;  
     6 import android.graphics.Paint;  
     7 import android.graphics.Typeface;  
     8 import android.graphics.Bitmap.Config;  
     9 import android.util.AttributeSet;  
    10 import android.view.View;  
    11   
    12 public class MyView extends View{  
    13   
    14     private Paint paint  = new Paint() ;  
    15       
    16     public MyView(Context context) {  
    17         super(context);  
    18         // TODO Auto-generated constructor stub  
    19     }  
    20     public MyView(Context context , AttributeSet attrs){  
    21         super(context,attrs);  
    22     }  
    23     //存在canvas對象,即存在默認的顯示區域  
    24     @Override  
    25     public void draw(Canvas canvas) {  
    26         // TODO Auto-generated method stub  
    27         super.draw(canvas);  
    28         //加粗  
    29         paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));  
    30         paint.setColor(Color.BLUE);  
    31         canvas.drawText("自定義View,canvas對象已經存在。", 30, 40, paint);  
    32         canvas.drawRect(10, 10, 30, 30, paint);  
    33           
    34         //將icon圖像轉換為Bitmap對象  
    35         Bitmap iconbit = BitmapFactory.decodeResource(getResources(), R.drawable.icon) ;  
    36         canvas.drawBitmap(iconbit, 40,40, paint);  
    37     }  
    38 }  

     


  3、主工程文件 MainActivity.java

  1.  1 public class MainActivity extends Activity {  
     2     //畫筆對象 paint  
     3     private Paint paint = new Paint() ;   //記得要為paint設置顏色,否則 看不到效果  
     4     private ImageView imgClip ;  // 繪圖區域以及clip方法  
     5     private ImageView imgSave ;  // save方法以及restore  
     6       
     7     /** Called when the activity is first created. */  
     8     @Override  
     9     public void onCreate(Bundle savedInstanceState) {  
    10         super.onCreate(savedInstanceState);  
    11           setContentView(R.layout.main) ;  
    12             
    13           imgClip = (ImageView)findViewById(R.id.imgClip) ;  
    14           imgSave = (ImageView)findViewById(R.id.imgSave);  
    15             
    16           clip_drawCanvas() ; // 繪圖區域以及clip方法  
    17           save_drawCanvas();  // save方法以及restore  
    18     }  
    19     //這樣的情況下,需要創建Canvas對象,然后在此對象上進行操作  
    20     //對bitmap操作完成后,,顯示該Bitmap有以下兩種操作。  
    21     //1、需要將bitmap轉換為Drawable對象  Drawable drawable = new BitmapDrawable(bitmap) ;  
    22     //2、直接setImageBitmap(bitmap)  
    23     private void  clip_drawCanvas(){  
    24         //將icon圖像轉換為Bitmap對象  
    25         Bitmap iconbit = BitmapFactory.decodeResource(getResources(), R.drawable.icon) ;  
    26           
    27         //創建一個的Bitmap對象  
    28         Bitmap bitmap = Bitmap.createBitmap(200, 150, Config.ARGB_8888)  ;  
    29           
    30         Canvas canvas = new Canvas (bitmap) ;  
    31         //設置顏色來顯示畫圖區域  
    32         canvas.drawColor(Color.RED);  
    33   
    34         paint.setColor(Color.BLACK);  
    35         canvas.drawText("原先的畫圖區域--紅色部分", 60,50,paint) ;  
    36         //畫bitmap對象  
    37         canvas.drawBitmap(iconbit, 20, 20, paint);  
    38           
    39         //剪裁一個區域,當前的操作對象為Rect裁剪的區域  
    40         Rect rect = new Rect (10,80,180,120) ;  
    41           
    42         //當前的畫圖區域為Rect裁剪的區域,而不是我們之前賦值的bitmap  
    43         canvas.clipRect(rect)  ;  
    44         canvas.drawColor(Color.YELLOW);  
    45         //設置顏色來顯示畫圖區域  
    46         paint.setColor(Color.BLACK);  
    47         canvas.drawText("裁剪clip后畫圖區域-黃色部分", 10,100,paint) ;  
    48           
    49         //將Bitmap對象轉換為Drawable圖像資源  
    50         //Drawable drawable = new BitmapDrawable(bitmap) ;  
    51         //img.setBackgroundDrawable(drawable) ;  
    52           
    53         //顯示,同上  
    54         imgClip.setImageBitmap(bitmap);  
    55     }  
    56       
    57     private void save_drawCanvas(){  
    58         //將icon圖像轉換為Bitmap對象  
    59         Bitmap iconbit = BitmapFactory.decodeResource(getResources(), R.drawable.icon) ;  
    60           
    61         //創建一個的Bitmap對象  
    62         Bitmap bitmap = Bitmap.createBitmap(200, 100, Config.ARGB_8888)  ;  
    63      
    64         Canvas canvas = new Canvas (bitmap) ;  
    65   
    66         paint.setColor(Color.GREEN);  
    67         paint.setTextSize(16);  //設置字體大小  
    68         canvas.drawRect(10, 10, 50, 8, paint);  
    69         canvas.drawText("我沒有旋轉",50, 10, paint);  
    70         //保存canvas之前的操作,在sava()和restore之間的操作不會對canvas之前的操作進行影響  
    71         canvas.save() ;  
    72           
    73         //順時針旋轉30度  
    74         canvas.rotate(30) ;  
    75         canvas.drawColor(Color.RED);  
    76         canvas.drawBitmap(iconbit, 20, 20, paint);  
    77         canvas.drawRect(50, 10, 80, 50, paint);  
    78         //canvas.translate(20,20);  
    79         canvas.drawText("我是旋轉的",115,20, paint);  
    80           
    81         //復原之前save()之前的屬性,並且將save()方法之后的roate(),translate()以及clipXXX()方法的操作清空  
    82         canvas.restore();  
    83           
    84         //平移(20,20)個像素  
    85         //canvas.translate(20,20);  
    86         canvas.drawRect(80, 10, 110,30, paint);  
    87         canvas.drawText("我沒有旋轉",115,20, paint);  
    88   
    89         //將Bitmap對象轉換為Drawable圖像資  
    90         //為ImageView設置圖像  
    91         //imgSave.setImageBitmap(bitmap);  
    92           
    93         Drawable drawable = new BitmapDrawable(bitmap) ;  
    94         imgSave.setBackgroundDrawable(drawable) ;  
    95           
    96     }  
    97 }  

     


          總的來說,Canvas理解起來還是比較糾結的,尤其是它的幾個方法真是讓人頭疼, 希望你能夠自己編寫相應的代碼

  理解透徹,才真正的有所收獲。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM