初学Android,图形图像之使用双缓冲画图(二十七)

来源:互联网 发布:mac os beta版 编辑:程序博客网 时间:2024/05/24 01:42
当数据量很大时,绘图可能需要几秒钟甚至更长的时间,而且有时还会出现闪烁现象,为了解决这些问题,可采用双缓冲技术来绘图。
 双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。双缓冲实现过程如下:
  1、在内存中创建与画布一致的缓冲区
  2、在缓冲区画图
  3、将缓冲区位图拷贝到当前画布上

  4、释放内存缓冲区

下面的例子(一个画图板)将实现双缓冲画图

先自定义一个View(Bitmap将会绘制到这个View上)

[java] view plain copy
 print?
  1. <span style="font-size:14px;">package Wangli.Graphics.HandDraw;  
  2. import android.content.Context;  
  3. import android.graphics.Bitmap;  
  4. import android.graphics.Bitmap.Config;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Color;  
  7. import android.graphics.Paint;  
  8. import android.graphics.Path;  
  9. import android.util.AttributeSet;  
  10. import android.view.MotionEvent;  
  11. import android.view.View;  
  12.   
  13. public class DrawView extends View {  
  14.     float preX;  
  15.     float preY;  
  16.     private Path path;  
  17.     public Paint paint = null;  
  18.     final int VIEW_WIDTH = 320;  
  19.     final int VIEW_HEIGHT = 480;  
  20.     //定义一个内存中的图片,该图片将作为缓冲区  
  21.     Bitmap cacheBitmap = null;  
  22.     //定义cacheBitmap上的canvas对象  
  23.     Canvas cacheCanvas = null;  
  24.     public DrawView(Context context, AttributeSet attrs) {  
  25.         super(context, attrs);  
  26.         //创建一个与该View相同大小的缓存区  
  27.         cacheBitmap = Bitmap.createBitmap(VIEW_WIDTH,VIEW_HEIGHT,Config.ARGB_8888);  
  28.         cacheCanvas = new Canvas();  
  29.         path = new Path();  
  30.         //设置cacheCanvas将会绘制到内存中的cacheBitmap上  
  31.         cacheCanvas.setBitmap(cacheBitmap);  
  32.         //设置画笔的颜色  
  33.         paint = new Paint(Paint.DITHER_FLAG);  
  34.         paint.setColor(Color.RED);  
  35.         //设置画笔的风格  
  36.         paint.setStyle(Paint.Style.STROKE);  
  37.         paint.setStrokeWidth(1);  
  38.         //反锯齿  
  39.         paint.setAntiAlias(true);  
  40.         paint.setDither(true);  
  41.     }  
  42.     public boolean onTouchEvent(MotionEvent event)  
  43.     {  
  44.         //获取拖动事件发生的位置  
  45.         float x = event.getX();  
  46.         float y = event.getY();  
  47.         switch(event.getAction())  
  48.         {  
  49.             case MotionEvent.ACTION_DOWN:  
  50.                  path.moveTo(x, y);  
  51.                  preX = x;  
  52.                  preY = y;  
  53.                  break;  
  54.             case MotionEvent.ACTION_MOVE:  
  55.                  path.quadTo(preX, preY, x, y);  
  56.                  preX = x;  
  57.                  preY = y;  
  58.                  break;  
  59.             case MotionEvent.ACTION_UP:  
  60.                  cacheCanvas.drawPath(path, paint);  
  61.                  path.reset();  
  62.                  break;  
  63.         }  
  64.         invalidate();  
  65.         //返回true表明处理方法已经处理该事件  
  66.         return true;  
  67.     }  
  68.     public void onDraw(Canvas canvas)  
  69.     {  
  70.         Paint bmpPaint = new Paint();  
  71.         //将cacheBitmap绘制到该View组件上  
  72.         canvas.drawBitmap(cacheBitmap, 00, bmpPaint);  
  73.         //沿着path绘制  
  74.         canvas.drawPath(path, paint);  
  75.     }  
  76. }</span><span style="font-size:12px;">  
  77. </span>  
定义菜单资源文件my_menu

[html] view plain copy
 print?
  1. <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>  
  2. <menu xmlns:android="http://schemas.android.com/apk/res/android">  
  3.     <item android:title="@string/color">  
  4.         <menu>  
  5.             <!-- 定义一组单选菜单项 -->  
  6.             <group android:checkableBehavior="single">  
  7.                 <!-- 定义多个菜单项 -->  
  8.                 <item  
  9.                     android:id="@+id/red" android:title="@string/color_red"/>  
  10.                 <item  
  11.                     android:id="@+id/green" android:title="@string/color_green"/>  
  12.                 <item  
  13.                     android:id="@+id/blue" android:title="@string/color_blue"/>  
  14.             </group>  
  15.         </menu>  
  16.     </item>  
  17.     <item android:title="@string/width">  
  18.         <menu>  
  19.             <!-- 定义一组菜单项 -->  
  20.             <group>  
  21.                 <!-- 定义3个菜单项 -->  
  22.                 <item  
  23.                     android:id="@+id/width_1" android:title="@string/width_1"/>  
  24.                 <item  
  25.                     android:id="@+id/width_3" android:title="@string/width_3"/>  
  26.                 <item  
  27.                     android:id="@+id/width_5" android:title="@string/width_5"/>                        
  28.             </group>  
  29.         </menu>  
  30.     </item>  
  31.     <item  
  32.         android:id="@+id/blur" android:title="@string/blur"/>      
  33.     <item  
  34.         android:id="@+id/emboss" android:title="@string/emboss"/>                              
  35. </menu></span>  
strings.xml

[html] view plain copy
 print?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   <string name="hello">Hello World, HandDraw!</string>   
  4.   <string name="app_name">手绘</string>   
  5.   <string name="width_1">1像素</string>   
  6.   <string name="width_3">3像素</string>   
  7.   <string name="width_5">5像素</string>   
  8.   <string name="color_red">红色</string>   
  9.   <string name="color_green">绿色</string>   
  10.   <string name="color_blue">蓝色</string>   
  11.   <string name="color">画笔颜色</string>   
  12.   <string name="width">画笔宽度</string>   
  13.   <string name="blur">模糊效果</string>   
  14.   <string name="emboss">浮雕效果</string>   
  15. </resources>  
主界面处理菜单事件 

[java] view plain copy
 print?
  1. package Wangli.Graphics.HandDraw;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.BlurMaskFilter;  
  5. import android.graphics.Color;  
  6. import android.graphics.EmbossMaskFilter;  
  7. import android.os.Bundle;  
  8. import android.view.Menu;  
  9. import android.view.MenuInflater;  
  10. import android.view.MenuItem;  
  11.   
  12. public class HandDraw extends Activity {  
  13.     /** Called when the activity is first created. */  
  14.     EmbossMaskFilter emboss;  
  15.     BlurMaskFilter blur;  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.         emboss = new EmbossMaskFilter(new float[]{1.5f,1.5f,1.5f},0.6f,6,4.2f);  
  21.         blur = new BlurMaskFilter(8,BlurMaskFilter.Blur.NORMAL);  
  22.     }  
  23.     //负责创建选项菜单  
  24.     public boolean onCreateOptionsMenu(Menu menu)  
  25.     {  
  26.         MenuInflater inflator = new MenuInflater(this);  
  27.         //状态R.menu.context对应菜单,并添加到中  
  28.         inflator.inflate(R.menu.my_menu,menu);  
  29.         return super.onCreateOptionsMenu(menu);  
  30.     }  
  31.     //菜单项被单击后的回调方法  
  32.     public boolean onOptionsItemSelected(MenuItem mi)  
  33.     {  
  34.         DrawView dv = (DrawView)findViewById(R.id.draw);  
  35.         //判断单击的是哪个菜单项,并有针对性地做出响应  
  36.         switch(mi.getItemId())  
  37.         {  
  38.             case R.id.red:  
  39.                 dv.paint.setColor(Color.RED);  
  40.                 mi.setChecked(true);  
  41.                 break;  
  42.             case R.id.green:  
  43.                 dv.paint.setColor(Color.GREEN);  
  44.                 mi.setChecked(true);  
  45.                 break;  
  46.             case R.id.blue:  
  47.                 dv.paint.setColor(Color.BLUE);  
  48.                 mi.setChecked(true);  
  49.                 break;  
  50.             case R.id.width_1:  
  51.                 dv.paint.setStrokeWidth(1);  
  52.                 mi.setChecked(true);  
  53.                 break;  
  54.             case R.id.width_3:  
  55.                 dv.paint.setStrokeWidth(3);  
  56.                 mi.setChecked(true);  
  57.                 break;  
  58.             case R.id.width_5:  
  59.                 dv.paint.setStrokeWidth(5);  
  60.                 mi.setChecked(true);  
  61.                 break;  
  62.             case R.id.blur:  
  63.                 dv.paint.setMaskFilter(blur);  
  64.                 mi.setChecked(true);  
  65.                 break;  
  66.             case R.id.emboss:  
  67.                 dv.paint.setMaskFilter(emboss);  
  68.                 mi.setChecked(true);  
  69.                 break;  
  70.         }  
  71.         return true;  
  72.     }  
  73. }  
下面是实现效果



更改画笔效果

0 0