1. 程式人生 > >自定義View起步:Canvas之繪製圖片

自定義View起步:Canvas之繪製圖片

          在前面的章節中,我們已經介紹了Canvas的一些基本操作,今天我們繼續講解,Canvas類的用法,可見這個類在自定義View中是多麼的重要。今天我們來著重介紹一下如何繪製圖片和文字。在這一章節學習之後我們基本上對於一些簡單的自定義View就可以搞定了。但是這僅僅是剛剛開始,我還會繼續帶領大家深入的學習下去,做出更多更炫酷的自定義控制元件出來。

 第一、drawPicture繪製圖片

上面是官網中提供的此類的方法,beginRecording()意思為開始錄製,什麼意思呢。看一段官網的解釋再說:To record a picture, call beginRecording() and then draw into the Canvas that is returned. Nothing we appear on screen, but all of the draw commands (e.g. ) will be recorded. To stop recording, call endRecording(). After endRecording() the Canvas that was returned must no longer be used, and nothing should be drawn into it.意思是此方法開始記錄一幅畫,就是canvas的操作。直到endRecording()方法的呼叫,結束錄製。注意:endRecording()呼叫之後此畫布必須保證不再使用。什麼意思呢,我們可以通俗的理解為,此方法的操作是可以記錄一個畫布,然後重複的使用,每次使用都是和上一次一樣的。是不是這樣可以大大減少我們的記憶體開支,只要首次載入的時候繪製一遍,之後每次都使用記錄的內容就可以。後面是getHeight和getWidth兩個方法,獲取寬和高很簡單就不說了。最後一個輸出流,可以看到在API18之後已經廢棄了,就先不考慮了。

 第二、Picture的使用步驟

1、初始化物件

//第一步建立Picture
    private Picture mPicture = new Picture();

2、錄製畫布的操作

//開始錄製繪製的內容
private void recording(){
    //開始錄製圖片,返回一個canvas,此canvas的所有操作都將會被錄製。
Canvas canvas = mPicture.beginRecording(500,500);
//建立一個畫筆
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL
); //位移畫布中心點座標一段距離 canvas.translate(500,500); //繪製一個圓 canvas.drawCircle(0,0,300,paint); //錄製結束 mPicture.endRecording(); }

3、呼叫

public CustomPictureText(Context context, AttributeSet attrs) {
    super(context, attrs);
// 呼叫錄製
recording();
}

4、開始繪製

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
mPicture.draw(canvas); }

5、結果如圖

7、繪製的方法有很多,以上的方法在低版本中可能會影響Canvas的狀態。下面我們來介紹Canvas為我們提供的繪製方法。來比較一下有什麼差別

public void drawPicture (Picture picture)

public void drawPicture (Picture picture, Rect dst)

public void drawPicture (Picture picture, RectF dst)
 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
       canvas.drawPicture(mPicture,new RectF(0,0,mPicture.getWidth(),200));
       

    }


效果如圖:

如圖所示我們的圓變成了橢圓,是什麼造成的呢,這裡我們的繪製的時候傳入了一個矩形,這個矩形就是用來壓縮我們的begin開始錄製的時候返回的畫布的,當時我們設定為500,500.可以看到我們這裡的方法是寬保持不變,高度變為原來的二分之一一,就把原來的圓壓縮為現在的橢圓了。

8.將Picture包裝成為PictureDrawable,使用PictureDrawable的draw方法繪製。

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //包裝成drawable
        PictureDrawable drawable = new PictureDrawable(mPicture);
        //設定繪製的區域
        drawable.setBounds(0,0,500,mPicture.getHeight());
        drawable.draw(canvas);

    }

注意這裡的setBounds方法,來設定的是繪製區域,設定的是現在onDraw方法裡邊的畫布,而不是我們picture的畫布。設定的區域為左邊左上角0,0.到500,圖片高度。這裡將會展示出來一個四分之一的圓。

第三、drawBitmap繪製圖片

一提到Bitmap可能大多數的小夥伴都會有一種莫名其妙的不知所措,什麼記憶體溢位了,記憶體洩漏了,好像很多都是和Bitmap有關的,但是今天我們不會深入的去研究這裡邊的原理,今天我們先介紹一下,使用drawBitmap來繪製我們的圖片資源。既然是繪製Bitmap那麼我們肯定需要先獲取到Bitmap才對。獲取Bitmap我們使用BitmapFactory來獲取,他可以獲取,手機儲存卡,資原始檔,網路圖片轉換為我們使用的Bitmap。其實還有其他的兩種方法,但是今天我們就先介紹BitmaoFactory這個最常用的。

1、通過資原始檔獲取Bitmap(drawable/mipmap/raw)

Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.dafenqi);


2、通過assets獲取

 //從assets中獲取資原始檔
        Bitmap bitmap = null;
        try {
            InputStream inputStream = mContext.getAssets().open("dafenqi.png");
            bitmap = BitmapFactory.decodeStream(inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }


3、通過記憶體卡

Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/bitmap.png");

4、通過網路

 // 此處省略了獲取網路輸入流的程式碼
        Bitmap bitmap = BitmapFactory.decodeStream(is);
        is.close();

5、下面我們將itmap繪製到我們的介面上


第一種方法中後兩個引數(matrix, paint)是在繪製的時候對圖片進行一些改變,如果只是需要將圖片內容繪製出來只需要如下操作就可以了:


第二種方法就是在繪製時指定了圖片左上角的座標(距離座標原點的距離):

注意:此處指定的是與座標原點的距離,並非是與螢幕頂部和左側的距離, 雖然預設狀態下兩者是重合的,但是也請注意分別兩者的不同。

 canvas.drawBitmap(bitmap,200,500,new Paint());

第三種方法比較有意思,上面多了兩個矩形區域(src,dst),這兩個矩形選區是幹什麼用的?

// 將畫布座標系移動到畫布中央
        canvas.translate(mWidth/2,mHeight/2); //將畫布的中心圓點移動到中心位置

        // 指定圖片繪製區域(左上角的四分之一)
        Rect src = new Rect(0,0,bitmap.getWidth()/2,bitmap.getHeight()/2);

        // 指定圖片在螢幕上顯示的區域
        Rect dst = new Rect(0,0,200,200);

        // 繪製圖片
        canvas.drawBitmap(bitmap,src,dst,null);


詳解:

上面是以繪製該圖為例,用src指定了圖片繪製部分的區域,即下圖中紅色方框標註的區域。

然後用dst指定了繪製在螢幕上的繪製,即下圖中藍色方框標註的區域,圖片寬高會根據指定的區域自動進行縮放。