【注】本案例来自疯狂Android讲义,仅作为学习参考
这是一篇简单的关于android的手写板简单实现,效果是可在屏幕上绘制任意的图形。实现手绘功能其实是一种假象,表面上看起来可以随用户在触摸屏上自由的画线,实际上是利用Canvas的drawLine方法画直线,每条直线都是在上一次拖动事件发生点画到本次拖动事件发生点。借助Android的Path类,可以非常方便地实现这种效果。
这个设计思路是,当程序需要在指定View上进行绘制时,程序并不直接绘制到该View组件上,而是先绘制到一个内存中的Bitmap图片上,等到内存中的Bitmap绘制好之后,再一次性的将Bitmap绘制到View组件上。
(1)该View的代码如下。
package com.example.drawingtest.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class DrawView extends View { public Paint paint; // 定义一个内存中的图片,该图片将作为缓冲区 Bitmap cacheBitmap = null; // 定义cacheBitmap上的Canvas对象 Canvas cacheCanvas = null; float preX; float preY; final int VIEW_WIDTH = 320; final int VIEW_HEIGHT = 480; private Path path; private boolean isReset; public DrawView(Context context, AttributeSet attrs) { super(context, attrs); // 创建一个与该View相同大小的缓冲区 cacheBitmap = Bitmap.createBitmap(VIEW_WIDTH, VIEW_HEIGHT, Config.ARGB_8888); cacheCanvas = new Canvas(); path = new Path(); // 设置cacheCanvas将会绘制到内存中的cacheBitmap上 cacheCanvas.setBitmap(cacheBitmap); // 设置画笔的颜色 paint = new Paint(); paint.setColor(Color.RED); // 设置画笔的风格 paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(1); // 反锯齿 paint.setAntiAlias(true); paint.setDither(false); } @Override public boolean onTouchEvent(MotionEvent event) { // 获取拖动事件的发生位置 float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: path.moveTo(x, y); preX = x; preY = y; break; case MotionEvent.ACTION_MOVE: // 从触碰点作为控制点画曲线 path.quadTo(preX, preY, x, y); preX = x; preY = y; break; case MotionEvent.ACTION_UP: cacheCanvas.drawPath(path, paint); path.reset(); break; } invalidate(); // 返回true表明处理方法已经处理该事件 return true; } @Override protected void onDraw(Canvas canvas) { if (isReset) { cacheBitmap = Bitmap.createBitmap(VIEW_WIDTH, VIEW_HEIGHT, Config.ARGB_8888); cacheCanvas = new Canvas(); path = new Path(); cacheCanvas.setBitmap(cacheBitmap); isReset = !isReset; } Paint bmpPaint = new Paint(); // 将cacheBitmap绘制到该View组件上(对缓存了Bitmap的Cancas进行绘图) canvas.drawBitmap(cacheBitmap, 0, 0, bmpPaint); // 沿着path绘制 canvas.drawPath(path, paint); } /** * 清理界面 */ public void reset() { cacheBitmap = null; isReset = true; invalidate(); } }
package com.example.drawingtest; import com.example.drawingtest.view.DrawView; import android.app.Activity; import android.graphics.BlurMaskFilter; import android.graphics.Color; import android.graphics.EmbossMaskFilter; import android.os.Bundle; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; public class HandDraw extends Activity { EmbossMaskFilter emboss; BlurMaskFilter blur; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.handdraw_layout); emboss = new EmbossMaskFilter(new float[]{1.5f,1.5f,1.5f}, 0.6f, 6, 4.2f); blur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = new MenuInflater(this); inflater.inflate(R.menu.my_menu, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { DrawView dv = (DrawView) findViewById(R.id.hand_draw_view); switch (item.getItemId()) { case R.id.red: dv.paint.setColor(Color.RED); item.setChecked(true); break; case R.id.green: dv.paint.setColor(Color.GREEN); item.setChecked(true); break; case R.id.blue: dv.paint.setColor(Color.BLUE); item.setChecked(true); break; case R.id.width_1: dv.paint.setStrokeWidth(1); break; case R.id.width_3: dv.paint.setStrokeWidth(3); break; case R.id.width_5: dv.paint.setStrokeWidth(5); break; case R.id.blur: dv.paint.setMaskFilter(blur); break; case R.id.emboss: dv.paint.setMaskFilter(emboss); break; case R.id.clear: dv.reset(); break; } return true; } }(3)截图效果。
上面的程序很简单。