|
1 package tz.signaturecapture; |
|
2 |
|
3 import java.io.OutputStream; |
|
4 |
|
5 import android.content.Context; |
|
6 import android.graphics.Bitmap; |
|
7 import android.graphics.Canvas; |
|
8 import android.graphics.Color; |
|
9 import android.graphics.Paint; |
|
10 import android.graphics.Path; |
|
11 import android.graphics.RectF; |
|
12 import android.util.AttributeSet; |
|
13 import android.util.Log; |
|
14 import android.view.MotionEvent; |
|
15 import android.view.View; |
|
16 |
|
17 public class SignatureWidget extends View |
|
18 { |
|
19 private static final float STROKE_WIDTH = 5f; |
|
20 private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2; |
|
21 private Paint paint = new Paint(); |
|
22 private Path path = new Path(); |
|
23 |
|
24 private float lastTouchX; |
|
25 private float lastTouchY; |
|
26 private final RectF dirtyRect = new RectF(); |
|
27 |
|
28 public SignatureWidget(Context context, AttributeSet attrs) |
|
29 { |
|
30 super(context, attrs); |
|
31 paint.setAntiAlias(true); |
|
32 paint.setColor(Color.BLACK); |
|
33 paint.setStyle(Paint.Style.STROKE); |
|
34 paint.setStrokeJoin(Paint.Join.ROUND); |
|
35 paint.setStrokeWidth(STROKE_WIDTH); |
|
36 } |
|
37 |
|
38 public void save(View parent, OutputStream os) |
|
39 { |
|
40 Log.v("log_tag", "Width: " + parent.getWidth()); |
|
41 Log.v("log_tag", "Height: " + parent.getHeight()); |
|
42 Bitmap bm = Bitmap.createBitmap(parent.getWidth(), parent.getHeight(), Bitmap.Config.RGB_565);; |
|
43 Canvas canvas = new Canvas(bm); |
|
44 parent.draw(canvas); |
|
45 bm.compress(Bitmap.CompressFormat.PNG, 90, os); |
|
46 } |
|
47 |
|
48 public void clear() |
|
49 { |
|
50 path.reset(); |
|
51 invalidate(); |
|
52 } |
|
53 |
|
54 @Override |
|
55 protected void onDraw(Canvas canvas) |
|
56 { |
|
57 canvas.drawPath(path, paint); |
|
58 } |
|
59 |
|
60 @Override |
|
61 public boolean onTouchEvent(MotionEvent event) |
|
62 { |
|
63 float eventX = event.getX(); |
|
64 float eventY = event.getY(); |
|
65 |
|
66 switch (event.getAction()) |
|
67 { |
|
68 case MotionEvent.ACTION_DOWN: |
|
69 path.moveTo(eventX, eventY); |
|
70 lastTouchX = eventX; |
|
71 lastTouchY = eventY; |
|
72 return true; |
|
73 |
|
74 case MotionEvent.ACTION_MOVE: |
|
75 |
|
76 case MotionEvent.ACTION_UP: |
|
77 |
|
78 resetDirtyRect(eventX, eventY); |
|
79 int historySize = event.getHistorySize(); |
|
80 for (int i = 0; i < historySize; i++) |
|
81 { |
|
82 float historicalX = event.getHistoricalX(i); |
|
83 float historicalY = event.getHistoricalY(i); |
|
84 expandDirtyRect(historicalX, historicalY); |
|
85 path.lineTo(historicalX, historicalY); |
|
86 } |
|
87 path.lineTo(eventX, eventY); |
|
88 break; |
|
89 |
|
90 default: |
|
91 debug("Ignored touch event: " + event.toString()); |
|
92 return false; |
|
93 } |
|
94 |
|
95 invalidate((int) (dirtyRect.left - HALF_STROKE_WIDTH), |
|
96 (int) (dirtyRect.top - HALF_STROKE_WIDTH), |
|
97 (int) (dirtyRect.right + HALF_STROKE_WIDTH), |
|
98 (int) (dirtyRect.bottom + HALF_STROKE_WIDTH)); |
|
99 |
|
100 lastTouchX = eventX; |
|
101 lastTouchY = eventY; |
|
102 |
|
103 return true; |
|
104 } |
|
105 |
|
106 private void debug(String string){ |
|
107 } |
|
108 |
|
109 private void expandDirtyRect(float historicalX, float historicalY) |
|
110 { |
|
111 if (historicalX < dirtyRect.left) |
|
112 { |
|
113 dirtyRect.left = historicalX; |
|
114 } |
|
115 else if (historicalX > dirtyRect.right) |
|
116 { |
|
117 dirtyRect.right = historicalX; |
|
118 } |
|
119 |
|
120 if (historicalY < dirtyRect.top) |
|
121 { |
|
122 dirtyRect.top = historicalY; |
|
123 } |
|
124 else if (historicalY > dirtyRect.bottom) |
|
125 { |
|
126 dirtyRect.bottom = historicalY; |
|
127 } |
|
128 } |
|
129 |
|
130 private void resetDirtyRect(float eventX, float eventY) |
|
131 { |
|
132 dirtyRect.left = Math.min(lastTouchX, eventX); |
|
133 dirtyRect.right = Math.max(lastTouchX, eventX); |
|
134 dirtyRect.top = Math.min(lastTouchY, eventY); |
|
135 dirtyRect.bottom = Math.max(lastTouchY, eventY); |
|
136 } |
|
137 } |