前言
根據(jù)Gcssloop所學(xué)習(xí)的自定義View整理與筆記驾茴。
準(zhǔn)備
** 禁用GPU硬件加速**
- 在AndroidManifest.xml文件為application標(biāo)簽添加如下的屬性即可為整個(gè)應(yīng)用程序開啟/關(guān)閉硬件加速:
<application android:hardwareAccelerated="false" ...>
- 在Activity 標(biāo)簽下使用 hardwareAccelerated 屬性開啟或關(guān)閉硬件加速:
<activity android:hardwareAccelerated="false" />
- 在Window 層級(jí)使用如下代碼開啟硬件加速:(Window層級(jí)不支持關(guān)閉硬件加速)
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
- View 級(jí)別如下關(guān)閉硬件加速:(view 層級(jí)上不支持開啟硬件加速)
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
或者使用android:layerType=”software”來關(guān)閉硬件加速
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingLeft="2dp"
android:layerType="software"
android:paddingRight="2dp" >
一哑蔫、drawPicture:錄制Canvas中繪制的內(nèi)容
** 使用Picture前請(qǐng)關(guān)閉硬件加速,以免引起不必要的問題!**
詳情請(qǐng)進(jìn)入這里->Android的硬件加速及可能導(dǎo)致的問題
首先乃沙,了解一下Picture的方法吧~
public int getWidth ()//獲取寬度
public int getHeight ()//獲取高度
public Canvas beginRecording (int width, int height)//開始錄制 (返回一個(gè)Canvas熬甫,在Canvas中所有的繪制都會(huì)存儲(chǔ)在Picture中)
public void endRecording ()//結(jié)束錄制
public void draw (Canvas canvas)//將Picture中內(nèi)容繪制到Canvas中
現(xiàn)在開始使用啦?(?*)
- 第一步:使用Picture錄制內(nèi)容
//錄制內(nèi)容
private void recording() {
Canvas canvas = picture.beginRecording(500, 500);
canvas.translate(250, 250);
canvas.drawCircle(0, 0, 100, paint);
picture.endRecording();
}
- 第二步:將錄制的內(nèi)容顯示出來(三種方式)
- 使用Picture提供的draw方法繪制。
// 將Picture中的內(nèi)容繪制在Canvas上,一般不使用
picture.draw(canvas);
效果圖為:
- 使用Canvas提供的drawPicture方法繪制试读,會(huì)縮放杠纵。
public void drawPicture (Picture picture)
public void drawPicture (Picture picture, Rect dst)
public void drawPicture (Picture picture, RectF dst)
舉個(gè)栗子:
paint.setColor(Color.RED);
canvas.drawRect(0, 0, 100, 200, paint);
paint.setColor(Color.BLACK);
canvas.drawPicture(picture, new RectF(0, 0, 100, 200));
效果圖為:
**繪制的內(nèi)容根據(jù)選區(qū)進(jìn)行了縮放**
- 將Picture包裝成為PictureDrawable,使用PictureDrawable的draw方法繪制钩骇,不會(huì)縮放淡诗。
paint.setColor(Color.RED);
canvas.drawRect(0, 0, 250, picture.getHeight(), paint);
paint.setColor(Color.BLACK);
// 包裝成為Drawable
PictureDrawable drawable = new PictureDrawable(picture);
// 設(shè)置繪制區(qū)域 -- 注意此處所繪制的實(shí)際內(nèi)容不會(huì)縮放
drawable.setBounds(0, 0, 250, picture.getHeight());
// 繪制
drawable.draw(canvas);
效果圖:
此處setBounds是設(shè)置在畫布上的繪制區(qū)域,并非根據(jù)該區(qū)域進(jìn)行縮放伊履,也不是剪裁Picture韩容,每次都從Picture的左上角開始繪制
ps:三種方法的主要區(qū)別:
是否對(duì)Canvas有影響: 1有影響;2,3不影響
此處指繪制完成后是否會(huì)影響Canvas的狀態(tài)(Matrix clip等)
可操作性強(qiáng)弱: 1可操作性較弱;2,3可操作性較強(qiáng)
此處的可操作性可以簡(jiǎn)單理解為對(duì)繪制結(jié)果可控程度。
接下來上代碼嘍
二唐瀑、drawBitmap
看到bitmap有點(diǎn)怕怕的群凶,哈哈,內(nèi)存泄漏的大麻煩啊哄辣,GcsSloop簡(jiǎn)單的講解了一下请梢,那我也跟著簡(jiǎn)單的學(xué)一下講一下吧赠尾,嘿嘿
1.第一步:通過BitmapFactory從不同位置獲取Bitmap
//資源文件(drawable/mipmap/raw)中獲取
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),R.raw.bitmap);
//資源文件(assets)
Bitmap bitmap=null;
try {
InputStream is = mContext.getAssets().open("bitmap.png");
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
//內(nèi)存卡文件
Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/bitmap.png");
//網(wǎng)絡(luò)文件
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();
2.第二步:繪制Bitmap
- 第一種
/** * Draw the bitmap using the specified matrix. *
* @param bitmap The bitmap to draw
* @param matrix The matrix used to transform the bitmap when it is drawn
* @param paint May be null. The paint used to draw the bitmap
*/
public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(),
paint != null ? paint.getNativeInstance() : 0);
}
demo:
canvas.drawBitmap(bitmap,new Matrix(),new Paint());
2.第二種
/**
* @param bitmap The bitmap to be drawn
* @param left The position of the left side of the bitmap being drawn
* @param top The position of the top side of the bitmap being drawn
* @param paint The paint used to draw the bitmap (may be null)
*/
public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
throwIfCannotDraw(bitmap);
native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top,
paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity);
}
**left、top:此處指定的是與坐標(biāo)原點(diǎn)的距離毅弧,并非是與屏幕頂部和左側(cè)的距離, 雖然默認(rèn)狀態(tài)下兩者是重合的气嫁,但是也請(qǐng)注意分別兩者的不同。
**
demo:
canvas.drawBitmap(bitmap,200,200,new Paint());
3.第三種
/*
@param bitmap The bitmap to be drawn
* @param src May be null. The subset of the bitmap to be drawn
* @param dst The rectangle that the bitmap will be scaled/translated to fit into
* @param paint May be null. The paint used to draw the bitmap
*/
public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, @Nullable Paint paint);
demo:
// 將畫布坐標(biāo)系移動(dòng)到畫布中央
canvas.translate(200, 200);
// 指定圖片繪制區(qū)域(左上角的四分之一)
Rect src = new Rect(0, 0, bitmap.getWidth() / 2, bitmap.getHeight() / 2);
// 指定圖片在屏幕上顯示的區(qū)域
Rect dst = new Rect(0, 0, 100, 200);
// 繪制圖片
canvas.drawBitmap(bitmap, src, dst, null);
效果