当前位置:操作系统 > 安卓/Android >>

Android简单涂鸦以及撤销、重做的实现方法

前段时间研究了下涂鸦功能的实现,其实单独的涂鸦实现起来还是挺简单的,关键的技术难点是撤销与重做功能的实现。但是这里暂时只说明下涂鸦功能的实现,高手勿喷哈,而且该功能在Android  SDK提供的APIDemo当中就有的,但是如果能够将该地方的知识点搞懂的话,我认为View画图基本上是难不倒你了,特别是里面为什么要用一个中间的Bitmap。老规矩,还是先看看效果图吧:



代码如下:

1.package cn.ych.tuya;
2.
3.import java.io.File;
4.import java.io.FileNotFoundException;
5.import java.io.FileOutputStream;
6.import java.io.IOException;
7.import java.util.ArrayList;
8.import java.util.Iterator;
9.import java.util.List;
10.
11.import android.content.Context;
12.import android.graphics.Bitmap;
13.import android.graphics.Canvas;
14.import android.graphics.Paint;
15.import android.graphics.Path;
16.import android.graphics.Bitmap.CompressFormat;
17.import android.os.Environment;
18.import android.view.MotionEvent;
19.import android.view.View;
20./**
21.*
22.* @category: View实现涂鸦、撤销以及重做功能
23.* @author: 锋翼
24.* @link: www.apkstory.com
25.* @date: 2012.1.4
26.*
27.*/
28.public class TuyaView extends View {
29.
30.private Bitmap mBitmap;
31.private Canvas mCanvas;
32.private Path mPath;
33.private Paint mBitmapPaint;// 画布的画笔
34.private Paint mPaint;// 真实的画笔
35.private float mX, mY;//临时点坐标
36.private static final float TOUCH_TOLERANCE = 4;
37.
38.private int screenWidth, screenHeight;// 屏幕長寬
39.
40.public TuyaView(Context context, int w, int h) {
41.  super(context);
42.  screenWidth = w;
43.  screenHeight = h;
44.
45.  mBitmap = Bitmap.createBitmap(screenWidth, screenHeight,
46.    Bitmap.Config.ARGB_8888);
47.  // 保存一次一次绘制出来的图形
48.  mCanvas = new Canvas(mBitmap);
49.
50.  mBitmapPaint = new Paint(Paint.DITHER_FLAG);
51.  mPaint = new Paint();
52.  mPaint.setAntiAlias(true);
53.  mPaint.setStyle(Paint.Style.STROKE);
54.  mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘
55.  mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形状
56.  mPaint.setStrokeWidth(5);// 画笔宽度
57.
58.}
59.
60.@Override
61.public void onDraw(Canvas canvas) {
62.  canvas.drawColor(0xFFAAAAAA);
63.  // 将前面已经画过得显示出来
64.  canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
65.  if (mPath != null) {
66.   // 实时的显示
67.   canvas.drawPath(mPath, mPaint);
68.  }
69.}
70.
71.private void touch_start(float x, float y) {
72.  mPath.moveTo(x, y);
73.  mX = x;
74.  mY = y;
75.}
76.
77.private void touch_move(float x, float y) {
78.  float dx = Math.abs(x - mX);
79.  float dy = Math.abs(mY - y);
80.
81.  触摸间隔大于阈值才绘制路径
82.  if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
83.   // 从x1,y1到x2,y2画一条贝塞尔曲线,更平滑(直接用mPath.lineTo也是可以的)
84.   mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
85.   mX = x;
86.   mY = y;
87.  }
88.}
89.
90.private void touch_up() {
91.  mPath.lineTo(mX, mY);
92.  mCanvas.drawPath(mPath, mPaint);
93.  }
94.
95.@Override
96.public boolean onTouchEvent(MotionEvent event) {
97.  float x = event.getX();
98.  float y = event.getY();
99.
100.  switch (event.getAction()) {
101.  case MotionEvent.ACTION_DOWN:
102.   // 每次down下去重新new一个Path
103.   mPath = new Path();
104.
105.   touch_start(x, y);
106.   invalidate();
107.   break;
108.  case MotionEvent.ACTION_MOVE:
109.   touch_move(x, y);
110.   invalidate();
111.   break;
112.  case MotionEvent.ACTION_UP:
113.   touch_up();
114.   invalidate();
115.   break;
116.  }
117.  return true;
118.}
119.
120.}

上一讲当中,已经讲解了普通View实现涂鸦的功能,现在再来给涂鸦添加上撤销与重做的功能吧。撤销与重做在很多地方都是很重要的功能,比如PS里面、Word里面等等,而且大部分童鞋都能够想到要实现该功能应该需要用到堆栈,对于一些大牛的话可能就直接想到设计模式上面去了,比如命令模式就可以解决撤销与重做的问题。我们这里要讲解的是利用集合来完成该功能,其实也就是模拟栈,我相信你懂得。
老规矩,先上效果图: 

  \


 

代码如下:

1.package cn.ych.tuya;
2.
3.import java.io.File;
4.import java.io.FileNotFoundException;
5.import java.io.FileOutputStream;
6.import java.io.IOException;
7.import java.util.ArrayList;
8.import java.util.Iterator;
9.import java.util.List;
10.
11.import android.content.Context;
12.import android.graphics.Bitmap;
13.import android.graphics.Canvas;
14.import android.graphics.Paint;
15.import android.graphics.Path;
16.import android.graphics.Bitmap.CompressFormat;
17.import android.os.Environment;
18.import android.view.MotionEvent;
19.import android.view.View;
20./**
21.*
22.* @category: View实现涂鸦、撤销以及重做功能
23.* @author: 锋翼
24.* @link: www.apkstory.com
25.* @date: 2012.1.4
26.*
27.*/
28.public class TuyaView extends View {
29.
30.private Bitmap mBitmap;
31.private Canvas mCanvas;
32.private Path mPath;
33.private Paint mBitmapPaint;// 画布的画笔
34.private Paint mPaint;// 真实的画笔
35.private float mX, mY;// 临时点坐标
36.private static final float TOUCH_TOLERANCE = 4;
37.
38.// 保存Path路径的集合,用List集合来模拟栈
39.private static List<DrawPath> savePath;
40.// 记录Path路径的对象
41.private DrawPath dp;
42.
43.private int screenWidth, screenHeight;// 屏幕長寬
44.
45.private class DrawPath {
46.  public Path path;// 路径
47.  public Paint paint;// 画笔
48.}
49.
50.public TuyaView(Context context, int w, int h) {
51.  super(context);
52.  screenWidth = w;
53.  screenHeight = h;
54.
55.  mBitmap = Bitmap.createBitmap(screenWidth, screenHeight,
56.    Bitmap.Config.ARGB_8888);
57.  // 保存一次一次绘制出来的图形
58.  mCanvas = new Canvas(mBitmap);
59.
60.  mBitmapPaint = new Paint(Paint.DITHER_FLAG);
61.  mPaint = new Paint();
62.  mPaint.setAntiAlias(true);
63.  mPaint.setStyle(Paint.Style.STROKE);
64.  mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘
65.  mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形状
66.  mPaint.setStrokeWidth(5);// 画笔宽度
67.
68.  savePath = new ArrayList<DrawPath>();
69.}
70.
71.@Override
72.public void onDraw(Canvas canvas) {
73.  canvas.drawColor(0xFFAAAAAA);
74.  // 将前面已经画过得显示出来
75.  canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
76.  if (mPath != null) {
77.   // 实时的显示
78.   canvas.drawPath(mPath, m

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,