自定义view-drawBitmap 实现类似动画效果

https://blog.csdn.net/u010947098/article/details/72357120

1.http://www.gcssloop.com/customview/Canvas_PictureText   GcsSloop

本篇文章讲的是,canvas绘制bitmap中的drawBitmap函数的一个比较有意思的使用方法,我们以后也许会用到也说不定的哦。

我们先来浏览一下这个函数:

publicvoiddrawBitmap(Bitmapbitmap,Rectsrc,Rectdst,Paintpaint)

publicvoiddrawBitmap(Bitmapbitmap,Rectsrc,RectFdst,Paintpaint)

其中src和dst这两个矩形区域是用来做什么的?

Rect src:指定绘制图片的区域

Rect dst或RectF dst:指定图片在屏幕上的绘制(显示)区域

来看一个示例:

[java]  view plain  copy
  1. // 将画布坐标系移动到画布中央  
  2. canvas.translate(mWidth/2,mHeight/2);  
  3.   
  4. // 指定图片绘制区域(左上角的四分之一)  
  5. Rect src = new Rect(0,0,bitmap.getWidth()/2,bitmap.getHeight()/2);  
  6.   
  7. // 指定图片在屏幕上显示的区域  
  8. Rect dst = new Rect(0,0,200,400);  
  9.   
  10. // 绘制图片  
  11. canvas.drawBitmap(bitmap,src,dst,null);  

详解:

上面是以绘制该图为例,用src选择图片的绘制区域,即下图红色区域。

用dst指定图片绘制(显示)在屏幕上面的区域,也就是图片的实际显示区域,用户可以看到的,即下图中蓝色方框标注的区域,图片宽高会根据这个指定区域自动进行缩放。

从上面可知,第三种方法可以绘制图片的一部分到画布上,这有什么用呢?

如果你看过某些游戏的资源文件,你可能会看到如下的图片(图片来自网络):

用一张图片包含了大量的素材,在绘制的时候每次只截取一部分进行绘制,这样可以大大的减少素材数量,而且素材管理起来也很方便。
然而这和我们有什么关系呢?我们又不做游戏开发。

确实,我们不做游戏开发,但是在某些时候我们需要制作一些炫酷的效果,这些效果因为太复杂了用代码很难实现或者渲染效率不高。这时候很多人就会想起帧动画,

将动画分解成一张一张的图片然后使用帧动画制作出来,这种实现方式的确比较简单,但是一个动画效果的图片有十几到几十张,一个应用里面来几个这样炫酷的动画效果

就会导致资源文件出现一大堆,想找其中的某一张资源图片简直就是灾难啊有木有。但是把同一个动画效果的所有资源图片整理到一张图片上,会大大的减少资源文件数量

方便管理,妈妈再也不怕我找不到资源文件了,同时也节省了图片文件头、文件结束块以及调色板等占用的空间

下面是利用drawBitmap第三种方法制作的一个简单示例:
资源文件如下:

最终效果如下:

其实实现起来非常简单,跟上面示例的代码大致相同,只不过自定义了一个动画效果,可以看看代码:

[java]  view plain  copy
  1. package com.rick.customview.view.checkview;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Bitmap;  
  5. import android.graphics.BitmapFactory;  
  6. import android.graphics.Canvas;  
  7. import android.graphics.Paint;  
  8. import android.graphics.Rect;  
  9. import android.os.Handler;  
  10. import android.os.Message;  
  11. import android.support.annotation.Nullable;  
  12. import android.util.AttributeSet;  
  13. import android.util.Log;  
  14. import android.view.View;  
  15.   
  16. import com.rick.customview.R;  
  17.   
  18. /** 
  19.  * 利用drawBitmap第三种方法制作的一个简单示例 
  20.  * <p> 
  21.  * Created by MyPC on 2017/5/16. 
  22.  */  
  23.   
  24. public class CheckView extends View {  
  25.     private static final int ANIM_NULL = 0;         //动画状态-没有  
  26.     private static final int ANIM_CHECK = 1;        //动画状态-开启  
  27.     private static final int ANIM_UNCHECK = 2;      //动画状态-结束  
  28.   
  29.     private Context mContext;           // 上下文  
  30.     private int mWidth, mHeight;        // 宽高  
  31.     private Handler mHandler;           // handler  
  32.   
  33.     private Paint mPaint;  
  34.     private Bitmap mBitmap;  
  35.   
  36.     private int animCurrentPage = -1;       // 当前页码  
  37.     private int animMaxPage = 13;           // 总页数  
  38.     private int animDuration = 500;         // 动画时长  
  39.     private int animState = ANIM_NULL;      // 动画状态  
  40.   
  41.     private boolean isCheck = false;        // 是否只选中状态  
  42.   
  43.     public CheckView(Context context) {  
  44.         this(context, null);  
  45.     }  
  46.   
  47.     public CheckView(Context context, @Nullable AttributeSet attrs) {  
  48.         super(context, attrs);  
  49.         init(context);  
  50.     }  
  51.   
  52.     //初始化  
  53.     private void init(Context context) {  
  54.         mContext = context;  
  55.   
  56.         mPaint = new Paint();  
  57.         mPaint.setColor(0xffFF5317);  
  58.         mPaint.setStyle(Paint.Style.FILL);  
  59.         mPaint.setAntiAlias(true);  
  60.   
  61.         mBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.checkmark);  
  62.   
  63.         mHandler = new Handler() {  
  64.             @Override  
  65.             public void handleMessage(Message msg) {  
  66.                 super.handleMessage(msg);  
  67.                 if (animCurrentPage < animMaxPage && animCurrentPage >= 0) {  
  68.                     if (animState == ANIM_NULL) {  
  69.                         return;  
  70.                     }  
  71.                     if (animState == ANIM_CHECK) {  
  72.                         animCurrentPage++;  
  73.                     } else if (animState == ANIM_UNCHECK) {  
  74.                         animCurrentPage--;  
  75.                     }  
  76.                     invalidate();  
  77.                     this.sendEmptyMessageDelayed(0, animDuration / animMaxPage);  
  78.                     Log.e("AAA""current=" + animCurrentPage);  
  79.                 } else {  
  80.                     if (isCheck) {  
  81.                         animCurrentPage = animMaxPage - 1;  
  82.                     } else {  
  83.                         animCurrentPage = -1;  
  84.                     }  
  85.                     invalidate();  
  86.                     animState = ANIM_NULL;  
  87.                 }  
  88.             }  
  89.         };  
  90.     }  
  91.   
  92.     @Override  
  93.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  94.         super.onSizeChanged(w, h, oldw, oldh);  
  95.         mWidth = w;  
  96.         mHeight = h;  
  97.     }  
  98.   
  99.     @Override  
  100.     protected void onDraw(Canvas canvas) {  
  101.         super.onDraw(canvas);  
  102.   
  103.         // 移动坐标系到画布中央  
  104.         canvas.translate(mWidth / 2, mHeight / 2);  
  105.   
  106.         // 绘制背景圆形  
  107.         canvas.drawCircle(00240, mPaint);  
  108.   
  109.         // 得出图像边长  
  110.         int sideLength = mBitmap.getHeight();  
  111.   
  112.         // 得到图像选区 和 实际绘制位置  
  113.         Rect src = new Rect(sideLength * animCurrentPage, 0, sideLength * (animCurrentPage + 1), sideLength);  
  114.         Rect dst = new Rect(-200, -200200200);  
  115.   
  116.         // 绘制  
  117.         canvas.drawBitmap(mBitmap, src, dst, null);  
  118.     }  
  119.   
  120.     /** 
  121.      * 选择 
  122.      */  
  123.     public void check() {  
  124.         if (animState != ANIM_NULL || isCheck) {  
  125.             return;  
  126.         }  
  127.         animState = ANIM_CHECK;  
  128.         animCurrentPage = 0;  
  129.         mHandler.sendEmptyMessageDelayed(0, animDuration / animMaxPage);  
  130.         isCheck = true;  
  131.     }  
  132.   
  133.     /** 
  134.      * 取消选择 
  135.      */  
  136.     public void unCheck() {  
  137.         if (animState != ANIM_NULL || !isCheck) {  
  138.             return;  
  139.         }  
  140.         animState = ANIM_UNCHECK;  
  141.         animCurrentPage = animMaxPage - 1;  
  142.         mHandler.sendEmptyMessageDelayed(0, animDuration / animMaxPage);  
  143.         isCheck = false;  
  144.     }  
  145.   
  146.     /** 
  147.      * 设置动画时长 
  148.      * 
  149.      * @param animDuration 
  150.      */  
  151.     public void setAnimDuration(int animDuration) {  
  152.         if (animDuration <= 0)  
  153.             return;  
  154.         this.animDuration = animDuration;  
  155.     }  
  156.   
  157.   
  158.     /** 
  159.      * 设置背景圆形颜色 
  160.      * 
  161.      * @param color 
  162.      */  
  163.     public void setBackgroundColor(int color) {  
  164.         mPaint.setColor(color);  
  165.     }  
  166. }  
OK,drawBitmap的使用,在这里就结束了。

猜你喜欢

转载自blog.csdn.net/kongbaidepao/article/details/80549320