閱讀45 返回首頁    go 阿裏雲 go 技術社區[雲棲]


android塗鴉實現

類似米聊、微信上的塗鴉和手寫文字功能

實現原理是自定義View,通過手勢識別獲取軌跡,然後通過畫筆畫圖

這裏添加了手勢記錄功能,並不難理解

代碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
public class TuyaView extends View {
  
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;// 畫布的畫筆
private Paint mPaint;// 真實的畫筆
private float mX, mY;// 臨時點坐標
private static final float TOUCH_TOLERANCE = 4;
  
// 保存Path路徑的集合,用List集合來模擬棧
private static List<DrawPath> savePath;
// 記錄Path路徑的對象
private DrawPath dp;
  
private int screenWidth, screenHeight;// 屏幕長寬
  
private class DrawPath {
public Path path;// 路徑
public Paint paint;// 畫筆
}
  
public TuyaView(Context context, int w, int h) {
super(context);
screenWidth = w;
screenHeight = h;
  
mBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
// 保存一次一次繪製出來的圖形
mCanvas = new Canvas(mBitmap);
  
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);// 設置外邊緣
mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形狀
mPaint.setStrokeWidth(5);// 畫筆寬度
  
savePath = new ArrayList<DrawPath>();
}
  
@Override
public void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
// 將前麵已經畫過得顯示出來
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
if (mPath != null) {
// 實時的顯示
canvas.drawPath(mPath, mPaint);
}
}
  
private void touch_start(float x, float y) {
mPath.moveTo(x, y);
mX = x;
mY = y;
}
  
private void touch_move(float x, float y) {
float dx = Math.abs(x – mX);
float dy = Math.abs(mY – y);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
// 從x1,y1到x2,y2畫一條貝塞爾曲線,更平滑(直接用mPath.lineTo也是可以的)
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
  
private void touch_up() {
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
//將一條完整的路徑保存下來(相當於入棧操作)
savePath.add(dp);
mPath = null;// 重新置空
}
/**
* 撤銷的核心思想就是將畫布清空,
* 將保存下來的Path路徑最後一個移除掉,
* 重新將路徑畫在畫布上麵。
*/
public void undo() {
mBitmap = Bitmap.createBitmap(screenWidth, screenHeight,
Bitmap.Config.ARGB_8888);
mCanvas.setBitmap(mBitmap);// 重新設置畫布,相當於清空畫布
// 清空畫布,但是如果圖片有背景的話,則使用上麵的重新初始化的方法,用該方法會將背景清空掉…
if (savePath != null && savePath.size() > 0) {
// 移除最後一個path,相當於出棧操作
savePath.remove(savePath.size() – 1);
  
Iterator<DrawPath> iter = savePath.iterator();
while (iter.hasNext()) {
DrawPath drawPath = iter.next();
mCanvas.drawPath(drawPath.path, drawPath.paint);
}
invalidate();// 刷新
  
/*在這裏保存圖片純粹是為了方便,保存圖片進行驗證*/
String fileUrl = Environment.getExternalStorageDirectory()
.toString() + “/android/data/test.png”;
try {
FileOutputStream fos = new FileOutputStream(new File(fileUrl));
mBitmap.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
  
}
}
/**
* 重做的核心思想就是將撤銷的路徑保存到另外一個集合裏麵(棧),
* 然後從redo的集合裏麵取出最頂端對象,
* 畫在畫布上麵即可。
*/
public void redo(){
//如果撤銷你懂了的話,那就試試重做吧。
}
  
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
  
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 每次down下去重新new一個Path
mPath = new Path();
//每一次記錄的路徑對象是不一樣的
dp = new DrawPath();
dp.path = mPath;
dp.paint = mPaint;
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
  
}
  
   
  
調用的地方
  
public class TuyaActivity extends Activity {
  
private TuyaView tuyaView = null;
  
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
  
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
  
tuyaView = new TuyaView(this, dm.widthPixels, dm.heightPixels);
setContentView(tuyaView);
}
  
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {// 返回鍵
tuyaView.undo();
return true;
}
return super.onKeyDown(keyCode, event);
}
  
}

最後更新:2017-04-03 12:53:36

  上一篇:go android塗鴉實現
  下一篇:go 手機衛士09-防盜邏輯實現