Android 之简易涂鸦板

没有废话,简单粗暴。

1.创建一个自定义 view

创建一个 DrawView,继承自 android.view.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
public class DrawView extends View {

private int view_width = 0;//画板宽度
private int view_height = 0;//画板高度
private float preX;//起始点的 x 坐标
private float preY;//起始点的 y 坐标
private Path path;//路径
public Paint paint = null;//画笔
Bitmap cacheBitmap = null;//定义一个内存中的图片,该图片作为缓冲区
Canvas cacheCanvas = null;//定义 cacheBitmap 上的 Canvas 对象


/*构造方法*/
public DrawView(Context context, AttributeSet set){
super(context,set);

}

/*重写 onDraw 方法*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}

}

2.修改 xml 文件

修改 activity_main.xml 文件,并将自定义的 DrawView 添加到布局管理器中。

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<com.example.test.DrawView
android:id="@+id/drawView1"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</FrameLayout>

3.DrawView 的构造方法

在 DrawView 的构造方法中,首先获取屏幕的宽度和高度,并创建一个与该 view 相同大小的缓存区,然后创建一个新的画面,并实例化一个路径,再讲内存中的位图绘制到 cacheCanvas 中,最后实例化一个画笔,并设置画笔的相关属性。

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
//获取屏幕宽度
view_width = context.getResources().getDisplayMetrics().widthPixels;
//获取屏幕高度
view_height = context.getResources().getDisplayMetrics().heightPixels;

cacheBitmap = Bitmap.createBitmap(view_width,view_height, Bitmap.Config.ARGB_8888);
//创建一个新的画布
cacheCanvas = new Canvas();
path = new Path();
//在 cacheCanvas 上绘制 cacheBitmap
cacheCanvas.setBitmap(cacheBitmap);

paint = new Paint(Paint.DITHER_FLAG);
//设置默认的画笔颜色
paint.setColor(Color.RED);

//设置填充方式为描边
paint.setStyle(Paint.Style.STROKE);
//设置笔刷的图形样式
paint.setStrokeJoin(Paint.Join.ROUND);
//设置画笔转弯处的连接风格
paint.setStrokeCap(Paint.Cap.ROUND);
//设置默认的画笔的宽度
paint.setStrokeWidth(1);
//使用抗锯齿功能
paint.setAntiAlias(true);
//使用抖动效果
paint.setDither(true);

4.重写 onDraw 方法

在 DrawView 的 onDraw 方法中,设置背景颜色,绘制 cacheBitmap,绘制路径以及保存当前的状态到栈中,并调用 restore()方法恢复所保存的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
//设置背景颜色
canvas.drawColor(0xFFFFFFFF);
//采用默认设置创建一个画笔
Paint bmpPaint = new Paint();

//绘制cacheBitmap
canvas.drawBitmap(cacheBitmap,0,0,bmpPaint);
//绘制路径
canvas.drawPath(path,paint);
//保存 canvas 状态
canvas.save(Canvas.ALL_SAVE_FLAG);
//恢复 canvas 之前的保存状态,防止保存后对 canvas 执行的操作最后续的绘制有影响
canvas.restore();

5.重写 onTouchEvent 方法

在 DrawView 类中,重写onTouchEvent() 方法,为该视图添加触摸时间监听器,在该方法中,首先获取触摸时间发生的位置,然后应用 switch 对时间的不同状态添加响应代码,最后调用invalidate()方法更新视图。

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
@Override
public boolean onTouchEvent(MotionEvent event) {

//获取触摸时间发生的位置
float x = event.getX();
float y = event.getY();
switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

//将绘图的起始点移到(x,y)的坐标位置
path.moveTo(x,y);
preX = x;
preY = y;
break;
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(x-preX);
float dy = Math.abs(y-preY);

//判断是否在允许的范围内
if (dx>=5 || dy >= 5){
path.quadTo(preX,preY,(x+preX)/2,(y+preY)/2);
preX = x;
preY = y;
}
break;
case MotionEvent.ACTION_UP:
//绘制路径
cacheCanvas.drawPath(path,paint);
path.reset();
break;
}
invalidate();

//返回 true,表示处理方法已经处理该事件
return true;
}

6.编写 clear() 方法

写一个 clear() 方法,用来实现橡皮擦功能。

1
2
3
4
5
6
7
public void clear() {

//设置图形重叠时的处理方式
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
//设置橡皮擦的宽度
paint.setStrokeWidth(50);
}

7.编写 save() 方法

写一个方法,用来保存当前的绘图。

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

public void save() {

try {
saveBitmap("myPicture");
}catch (IOException e){
e.printStackTrace();
}
}

private void saveBitmap(String filename) throws IOException {

//创建文件对象
File file = new File("/sdcard/pictures/"+filename+".png");
//创建一个新文件
file.createNewFile();
//创建一个文件输出流对象
FileOutputStream out = new FileOutputStream(file);
//将绘图内容压缩成 PNG 格式输出到输出流对象中
cacheBitmap.compress(Bitmap.CompressFormat.PNG,100,out);
//将缓冲区的数据全部写出到输出流中
out.flush();
//关闭文件输出流对象
out.close();
}

8.设置权限

1
2
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

9.创建 menu 资源文件

在 res 目录下,创建menu 文件夹,在 menu 文件夹下,创建 toolsmenu.xml 资源文件。

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
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:title="@string/color">
<menu >
<!-- 定义一组单选菜单项 -->
<group android:checkableBehavior="single" >
<!-- 定义子菜单 -->
<item android:id="@+id/red" android:title="@string/color_red"/>
<item android:id="@+id/green" android:title="@string/color_green"/>
<item android:id="@+id/blue" android:title="@string/color_blue"/>
</group>
</menu>
</item>
<item android:title="@string/width">
<menu >
<!-- 定义子菜单 -->
<group>
<item android:id="@+id/width_1" android:title="@string/width_1"/>
<item android:id="@+id/width_2" android:title="@string/width_2"/>
<item android:id="@+id/width_3" android:title="@string/width_3"/>
</group>
</menu>
</item>
<item android:id="@+id/clear" android:title="@string/clear"/>
<item android:id="@+id/save" android:title="@string/save"/>
</menu>

10.添加选项菜单

<1>重写onCreateOptionsMenu方法

在 activity 文件中,重写onCreateOptionsMenu()方法,在该方法中,实例化一个MenuInflater对象,并解析菜单资源文件。

1
2
3
4
5
6
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = new MenuInflater(this);
menuInflater.inflate(R.menu.toolsmenu,menu);
return super.onCreateOptionsMenu(menu);
}

<2>重写onOptionsItemSelected方法

重写onOptionsItemSelected() 方法,分别对各个菜单项被选择时做出相应的处理。

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
@Override
public boolean onOptionsItemSelected(MenuItem item) {

//获取自定义视图
DrawView drawView = (DrawView)findViewById(R.id.drawView1);
//取消擦除效果
drawView.paint.setXfermode(null);
//初始化画笔的宽度
drawView.paint.setStrokeWidth(1);

switch (item.getItemId()){

//设置画笔的颜色为红色
case R.id.red:
drawView.paint.setColor(Color.RED);
item.setChecked(true);
break;
//设置画笔的颜色为绿色
case R.id.green:
drawView.paint.setColor(Color.GREEN);
item.setChecked(true);
break;
//设置画笔的颜色为蓝色
case R.id.blue:
drawView.paint.setColor(Color.BLUE);
item.setChecked(true);
break;
//设置画笔的宽度为1
case R.id.width_1:
drawView.paint.setStrokeWidth(1);
break;
//设置画笔的宽度为5
case R.id.width_2:
drawView.paint.setStrokeWidth(5);
break;
//设置画笔的宽度为10
case R.id.width_3:
drawView.paint.setStrokeWidth(10);
break;
//擦除绘画
case R.id.clear:
drawView.clear();
break;
//保存绘画
case R.id.save:
drawView.save();
break;
}

return true;
}

运行,就会得到一个简易的涂鸦板,可以改变画笔颜色,画笔宽度,擦除,保存等。

真是越来越有意思了呢!

-------------本文结束感谢您的阅读-------------
分享使我快乐!