02 自定义手写签名控件

手写签名

自定义 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
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.LinkedList;
public class PaintView extends View {
/**
* 存储所有的线条
*/
private LinkedList<LinkedList<FPoint>> mLines;
/**
* 存储撤回的线条
*/
private LinkedList<LinkedList<FPoint>> mRecyles;
private Paint mPaintLine;
private boolean isTouching;
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
// 设定画笔
mPaintLine = new Paint();
mPaintLine.setColor(Color.GREEN);
mPaintLine.setStrokeWidth(4);
// 建构线条数据结构对象
mLines = new LinkedList<>();
mRecyles = new LinkedList<>();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
// 离开屏幕
isTouching = false;
} else {
LinkedList<FPoint> line;
// 触摸开始
if (!isTouching) {
line = new LinkedList<>();
mLines.add(line);
isTouching = true;
} else {
// 开始滑动
line = mLines.getLast();
}
line.add(new FPoint(event.getX(), event.getY()));
postInvalidate();
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
for (LinkedList<FPoint> line : mLines) {
if (line.size() > 1) {
// 至少两个点才能画一条线
for (int i = 1; i < line.size(); i++) {
FPoint p1 = line.get(i - 1);
FPoint p2 = line.get(i);
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, mPaintLine);
}
}
}
}
public void clear() {
if (mLines != null) {
mLines.clear();
postInvalidate();
}
}
public void undo() {
if (mLines != null && mLines.size() > 0 && mRecyles != null) {
mRecyles.add(mLines.removeLast());
postInvalidate();
}
}
public void redo() {
if (mRecyles != null && mRecyles.size() > 0 && mLines != null) {
mLines.add(mRecyles.removeLast());
postInvalidate();
}
}
private class FPoint {
private float x, y;
private FPoint(float x, float y) {
this.x = x;
this.y = y;
}
}
}
界面操作代码
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
public class DemoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_demo);
final PaintView paintView = findViewById(R.id.paint_view);
findViewById(R.id.clear).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
paintView.clear();
}
});
findViewById(R.id.undo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
paintView.undo();
}
});
findViewById(R.id.redo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
paintView.redo();
}
});
}
}
界面布局
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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFF"
android:orientation="vertical">
<com.xxt.xtest.PaintView
android:id="@+id/paint_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<Button
android:id="@+id/clear"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="Clear"/>
<Button
android:id="@+id/undo"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="Undo"/>
<Button
android:id="@+id/redo"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="Redo"/>
</LinearLayout>
</LinearLayout>