【注】本案例来自疯狂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();
}
}
(2)显示界面。
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)截图效果。
上面的程序很简单。