Android Canvas之drawBitmap方法案例詳解
前面講了paint,后面會花幾篇主要講講canvas,并且由于最近項目比較緊,所以近期的文章都會“短小精悍”;
paint 作為畫筆,里面有非常多而強大的設(shè)置方法,比如設(shè)置顏色過濾器,設(shè)置位圖渲染、漸變,設(shè)置圖像的混合模式等等,而canvas呢?里面提供了哪些利器可以為我們所用,一起來看看:

通過上圖我們可以看到,canvas 里的方法基本可以分為這么幾類:
- save、restore 等與層的保存和回滾相關(guān)的方法;
- scale、rotate、clipXXX 等對畫布進行操作的方法;
- drawXXX 等一系列繪畫相關(guān)的方法;
所以canvas 我們也就可以分上面三塊逐個擊破,今天咱們主要看 drawXXX里的drawBitmap,看完之后一起做一個漂浮星空的小栗子;
在Canvas 里 drawBitmap 有如下方法可用 :

而咱們也主要講其中的 drawBitmap(Bitmap,Rect,Rect,Paint);
首先咱們創(chuàng)建一個View,照舊重寫里面的 onMeasure、onDraw、onSizeChanged,并且在 onSizeChanged 里拿到view的寬高:
public class DrawBitmapView extends View {
private Resources mResources;
private Paint mBitPaint;
private Bitmap mBitmap;
private Rect mSrcRect, mDestRect;
// view 的寬高
private int mTotalWidth, mTotalHeight;
public DrawBitmapView(Context context) {
super(context);
mResources = getResources();
initBitmap();
initPaint();
}
private void initPaint() {
mBitPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBitPaint.setFilterBitmap(true);
mBitPaint.setDither(true);
}
private void initBitmap() {
mBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.<span style="font-family: Arial, Helvetica, sans-serif;">beautiful_girl</span>))
.getBitmap();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mTotalWidth = w;
mTotalHeight = h;
}
}
上面我們通過
mBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.<span style="font-family: Arial, Helvetica, sans-serif;">beautiful_girl</span>))
.getBitmap();
拿到了對應(yīng)的bitmap,這時候我們?nèi)绻獙⑺L制在屏幕上,需要創(chuàng)建兩個Rect,其實只要明白了這兩個Rect的意義并會靈活運用就可以做出不少效果;
第一個Rect 代表要繪制的bitmap 區(qū)域,第二個 Rect 代表的是要將bitmap 繪制在屏幕的什么地方,我們一起來看下:
此時我先定義兩個Rect,mSrcRect 取值為整個Bitmap 區(qū)域 ,mDestRect 取值為view左上方和bitmap同樣大??;
private Rect mSrcRect, mDestRect;
mSrcRect = new Rect(0, 0, mBitWidth, mBitHeight); mDestRect = new Rect(0, 0, mBitWidth, mBitHeight);
在onDraw 里繪制該位圖:
canvas.drawBitmap(mBitmap, mSrcRect, mDestRect, mBitPaint);
此時繪制效果如下,在屏幕的左上方出現(xiàn)了個美女:

畫在左上方似乎缺乏美感,我們把美女畫在view的中心,沒錯,我們只需要改變mDestRect:
// 計算左邊位置 int left = mHalfWidth - mBitWidth / 2; // 計算上邊位置 int top = mHalfHeight - mBitHeight / 2; mDestRect = new Rect(left, top, left + mBitWidth, top + mBitHeight);
位置計算的時候,只需要注意在android屏幕坐標系里,左上角的位置是(0,0),往右往下為正,此時效果如下:

既然可以如此輕易的改變繪制的位置,那咱們不斷的改變bitmap繪制的位置,模擬一下translate效果;
我們向外提供兩個接口:
public void startTranslate() {
startTranslate(0, 0, 200, 200, 1000);
}
/**
* 移動位圖
*
* @param startLeft 起始左邊距
* @param startTop 起始距上邊距離
* @param toLeft 到達左邊距
* @param toTop 到達上邊距
* @param duration 時長
*/
public void startTranslate(int startLeft, int startTop, int toLeft, int toTop, long duration) {
mStartLeft = startLeft;
mStartTop = startTop;
mToLeft = toLeft;
mToTop = toTop;
// 使用ValueAnimator創(chuàng)建一個過程
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(duration);
valueAnimator.setInterpolator(new AccelerateInterpolator());
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
// 不斷重新計算上下左右位置
float fraction = (Float) animator.getAnimatedValue();
int currentLeft = (int) ((mToLeft - mStartLeft) * fraction + mStartLeft);
int currentTop = (int) ((mToTop - mStartTop) * fraction + mStartTop);
if (mDestRect == null) {
mDestRect = new Rect(currentLeft, currentTop, currentLeft + mBitWidth,
currentTop + mBitHeight);
}
mDestRect.left = currentLeft;
mDestRect.right = currentLeft + mBitWidth;
mDestRect.top = currentTop;
mDestRect.bottom = currentTop + mBitHeight;
// 重繪
postInvalidate();
}
});
valueAnimator.start();
}
Activity 里控制view的移動:
final DrawBitmapView drawBitmapView = new DrawBitmapView(this);
setContentView(drawBitmapView, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
drawBitmapView.startTranslate();
drawBitmapView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Random random = new Random();
int startLeft = random.nextInt(200);
int startTop = random.nextInt(250);
int toLeft = random.nextInt(550) + 200;
int toBottom = random.nextInt(1000) + 250;
drawBitmapView.startTranslate(startLeft, startTop, toLeft, toBottom, 1000);
return true;
}
});
}
點擊之后起始點和到達點隨機生成,此時效果如下:

相信到這里大家已經(jīng)能靈活控制bitmap的位置了,順勢咱們再做個水平縮放為0的小例子:
public void startScale(long duration) {
// 使用ValueAnimator創(chuàng)建一個過程
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1, 0);
valueAnimator.setDuration(duration);
valueAnimator.setInterpolator(new AccelerateInterpolator());
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
// 不斷重新計算上下左右位置
float fraction = (Float) animator.getAnimatedValue();
if (mDestRect == null) {
mDestRect = new Rect(0, 0, mBitWidth,
mBitHeight);
}
mDestRect.right = (int) (fraction * mBitWidth);
// 重繪
postInvalidate();
}
});
valueAnimator.start();
}
只需要不斷減小mDestRect.right即可,非常簡單,看下效果:

上面兩個例子都是通過改變mDestRect ,在哪些時候我們需要動態(tài)改變mSrcRect 呢?我前面講過一個水波紋的例子,那里面就是不斷截取水波紋的一部分,進行展示,由于是連續(xù)截取,所以視覺感受上是連續(xù)波紋效果,有興趣的同學可以看看參考下;
好了本篇就講這么多,有些同學可能會想,尼瑪,這么簡單的玩意兒能做毛線牛逼動效啊,其實往往再復(fù)雜的動效也就是由一個個小點組成的,而思路和方案的選取就已經(jīng)決定了能否成功的做出酷炫又如絲般順滑的效果,好的思路又往往來源于對簡單方法的深刻理解
到此這篇關(guān)于Android Canvas之drawBitmap方法案例詳解的文章就介紹到這了,更多相關(guān)Android Canvas之drawBitmap方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android消息通知Notification常用方法(發(fā)送消息和接收消息)
最近在做消息通知類Notification的相關(guān)業(yè)務(wù),利用閑暇時間總結(jié)一下,主要分為兩部分來記錄:發(fā)送消息和接收消息,對Android消息通知相關(guān)知識感興趣的朋友一起看看吧2024-02-02
Android應(yīng)用開發(fā)中數(shù)據(jù)的保存方式總結(jié)
這篇文章主要介紹了Android應(yīng)用開發(fā)中數(shù)據(jù)的保存方式總結(jié),包括對ROM、SD卡、SharedPreference這三種方式實現(xiàn)的核心代碼的精選,需要的朋友可以參考下2016-02-02
Android使用post方式上傳圖片到服務(wù)器的方法
這篇文章主要介紹了Android使用post方式上傳圖片到服務(wù)器的方法,結(jié)合實例形式分析了Android文件傳輸?shù)南嚓P(guān)技巧,需要的朋友可以參考下2016-03-03
Android 優(yōu)化之存儲優(yōu)化的實現(xiàn)
這篇文章主要介紹了Android 優(yōu)化之存儲優(yōu)化的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07
Android getBackground().setAlpha遇到問題解決辦法
這篇文章主要介紹了Android getBackground().setAlpha遇到問題解決辦法的相關(guān)資料用,getBackground().setAlpha,導(dǎo)致其他布局背景透明度都改變的問題,需要的朋友可以參考下2017-03-03
android利用ContentResolver訪問者獲取手機聯(lián)系人信息
這篇文章主要介紹了android利用ContentResolver訪問者獲取手機聯(lián)系人信息,非常具有實用價值,需要的朋友可以參考下。2017-02-02
Android通過LIstView顯示文件列表的兩種方法介紹
過ListView顯示SD卡中的文件列表一共有兩種方法,一是:通過繼承ListActivity顯示;二是:利用BaseAdapter顯示,具體實現(xiàn)如下,感興趣的朋友可以參考下哈2013-06-06

