自定義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指定了繪製在螢幕上的繪製,即下圖中藍色方框標註的區域,圖片寬高會根據指定的區域自動進行縮放。