1. 程式人生 > >Android 自定義View探索——圖片

Android 自定義View探索——圖片

繪製圖片

繪製有兩種方法,drawPicture(向量圖) 和 drawBitmap(點陣圖),接下來我們一一瞭解。

drawPicture

使用Picture前請關閉硬體加速,以免引起不必要的問題,因此在AndroidMenifest檔案中application節點下添上 android:hardwareAccelerated=”false”以關閉整個應用的硬體加速。

我們把Canvas繪製點,線,矩形等諸多操作用Picture錄製下來,下次需要的時候拿來就能用,使用Picture相比於再次呼叫繪圖API,開銷是比較小的,也就是說對於重複的操作可以更加省時省力。

可以把Picture看作是一個錄製Canvas操作的錄影機。

相關方法
public int getWidth () 獲取寬度
public int getHeight () 獲取高度
public Canvas beginRecording (int width, int height) 開始錄製 (返回一個Canvas,在Canvas中所有的繪製都會儲存在Picture中)
public void endRecording () 結束錄製
public void draw (Canvas canvas) 將Picture中內容繪製到Canvas中
public static Picture createFromStream (InputStream stream)

(已廢棄)通過輸入流建立一個Picture
public void writeToStream (OutputStream stream) (已廢棄)將Picture中內容寫出到輸出流中

很明顯,beginRecording 和 endRecording 是成對使用的,一個開始錄製,一個是結束錄製,兩者之間的操作將會儲存在Picture中。

來寫個Demo試試

// 1.建立Picture
private Picture mPicture = new Picture();

---------------------------------------------------------------

// 2.錄製內容方法
private void recording() { // 開始錄製 (接收返回值Canvas) Canvas canvas = mPicture.beginRecording(500, 500); // 建立一個畫筆 Paint paint = new Paint(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.FILL); // 在Canvas中具體操作 // 位移 canvas.translate(250,250); // 繪製一個圓 canvas.drawCircle(0,0,100,paint); mPicture.endRecording(); } --------------------------------------------------------------- // 3.在使用前呼叫(我在建構函式中呼叫了) public Canvas3(Context context, AttributeSet attrs) { super(context, attrs); recording(); // 呼叫錄製 }

可以看出,建立Picture的流程大致如此,在後期呼叫時相當方便。

Picture雖然方法就那麼幾個,但是具體使用起來還是分很多情況的,由於錄製的內容不會直接顯示,就像儲存的視訊不點選播放不會自動播放一樣,同樣,想要將Picture中的內容顯示出來就需要手動呼叫播放(繪製),將Picture中的內容繪製出來可以有以下幾種方法:

  1. 使用Picture提供的draw方法繪製。
  2. 使用Canvas提供的drawPicture方法繪製。
  3. 將Picture包裝成為PictureDrawable,使用PictureDrawable的draw方法繪製。

下面來逐一分析

  1. 使用Picture提供的draw方法繪製。
// 將Picture中的內容繪製在Canvas上
mPicture.draw(canvas);  

這種方法在比較低版本的系統上繪製後可能會影響Canvas狀態,所以這種方法一般不會使用。
2. 使用Canvas提供的drawPicture方法繪製
drawPicture有三種方法:

public void drawPicture (Picture picture)

public void drawPicture (Picture picture, Rect dst)

public void drawPicture (Picture picture, RectF dst)

和使用Picture的draw方法不同,Canvas的drawPicture不會影響Canvas狀態。

使用示例

canvas.drawPicture(mPicture,new RectF(0,0,mPicture.getWidth(),200));

這種方法制定了繪製區域,因此會產生縮放等效果

  1. 將Picture包裝成為PictureDrawable,使用PictureDrawable的draw方法繪製。
// 包裝成為Drawable
PictureDrawable drawable = new PictureDrawable(mPicture);
// 設定繪製區域 -- 注意此處所繪製的實際內容不會縮放
drawable.setBounds(0,0,250,mPicture.getHeight());
// 繪製
drawable.draw(canvas);

此處setBounds是設定在畫布上的繪製區域,並非根據該區域進行縮放,也不是剪裁Picture,每次都從Picture的左上角開始繪製。

drawBitmap

依照慣例先預覽一下drawBitmap的常用方法:

// 第一種
public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)

// 第二種
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)

// 第三種
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)

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

PS:圖片左上角位置預設為座標原點。

canvas.drawBitmap(bitmap,new Matrix(),new Paint());

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

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

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

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

Rect src 指定繪製圖片的區域
Rect dst 或RectF 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,400);

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