Android编程实现手绘及保存为图片的方法(附demo源码下载)

时间:2021-07-18 08:31:03

本文实例讲述了android编程实现手绘及保存为图片的方法。分享给大家供大家参考,具体如下:

运行效果图预览:

Android编程实现手绘及保存为图片的方法(附demo源码下载)

应 yzuo_08 要求做了此demo,跟以前那个手写板demo不同的是可以将画布的内容保存为图片。

附上关键代码:

mainview.java

 
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
package com.tszy.views;
import java.io.file;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import android.content.context;
import android.graphics.bitmap;
import android.graphics.bitmap.compressformat;
import android.graphics.bitmap.config;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.paint;
import android.graphics.path;
import android.util.attributeset;
import android.view.motionevent;
import android.view.view;
public class mainview extends view {
 private paint paint;
 private canvas cachecanvas;
 private bitmap cachebbitmap;
 private path path;
 private int clr_bg, clr_fg;
 public mainview(context context, attributeset attrs) {
  super(context, attrs);
  clr_bg = color.white;
  clr_fg = color.cyan;
  paint = new paint();
  paint.setantialias(true); // 抗锯齿
  paint.setstrokewidth(3); // 线条宽度
  paint.setstyle(paint.style.stroke); // 画轮廓
  paint.setcolor(clr_fg); // 颜色
  path = new path();
  // 创建一张屏幕大小的位图,作为缓冲
  cachebbitmap = bitmap.createbitmap(480, 800, config.argb_8888);
  cachecanvas = new canvas(cachebbitmap);
  cachecanvas.drawcolor(clr_bg);
 }
 public mainview(context context) {
  super(context);
 }
 @override
 protected void ondraw(canvas canvas) {
  canvas.drawcolor(clr_bg);
  // 绘制上一次的,否则不连贯
  canvas.drawbitmap(cachebbitmap, 0, 0, null);
  canvas.drawpath(path, paint);
 }
 /**
  * 清空画布
  */
 public void clear() {
  path.reset();
  cachecanvas.drawcolor(clr_bg);
  invalidate();
 }
 /**
  * 将画布的内容保存到文件
  * @param filename
  * @throws filenotfoundexception
  */
 public void savetofile(string filename) throws filenotfoundexception {
  file f = new file(filename);
  if(f.exists())
   throw new runtimeexception("文件:" + filename + " 已存在!");
  fileoutputstream fos = new fileoutputstream(new file(filename));
  //将 bitmap 压缩成其他格式的图片数据
  cachebbitmap.compress(compressformat.png, 50, fos);
  try {
   fos.close();
  } catch (ioexception e) {
   // todo auto-generated catch block
   e.printstacktrace();
  }
 }
 private float cur_x, cur_y;
 private boolean ismoving;
 @override
 public boolean ontouchevent(motionevent event) {
  // todo auto-generated method stub
  float x = event.getx();
  float y = event.gety();
  switch (event.getaction()) {
   case motionevent.action_down : {
    cur_x = x;
    cur_y = y;
    path.moveto(cur_x, cur_y);
    ismoving = true;
    break;
   }
   case motionevent.action_move : {
    if (!ismoving)
     break;
    // 二次曲线方式绘制
    path.quadto(cur_x, cur_y, x, y);
    // 下面这个方法貌似跟上面一样
    // path.lineto(x, y);
    cur_x = x;
    cur_y = y;
    break;
   }
   case motionevent.action_up : {
    // 鼠标弹起保存最后状态
    cachecanvas.drawpath(path, paint);
    path.reset();
    ismoving = false;
    break;
   }
  }
  // 通知刷新界面
  invalidate();
  return true;
 }
}

activity 代码:

 
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
@override
public void onclick(view v) {
  // todo auto-generated method stub
  switch (v.getid()) {
   case r.id.iv_btn_clear :
    view.clear();
    break;
   case r.id.iv_btn_save : {
    try {
     string sdstate = environment.getexternalstoragestate(); // 判断sd卡是否存在
     // 检查sd卡是否可用
     if (!sdstate.equals(android.os.environment.media_mounted)) {
      toast.maketext(this, "sd卡未准备好!", toast.length_short).show();
      break;
     }
     //获取系统图片存储路径
     file path = environment.getexternalstoragepublicdirectory(environment.directory_pictures);
     // make sure the pictures directory exists.
     path.mkdirs();
     //根据当前时间生成图片名称
     calendar c = calendar.getinstance();
     string name = ""
       + c.get(calendar.year) + c.get(calendar.month) + c.get(calendar.day_of_month)
       + c.get(calendar.hour_of_day) + c.get(calendar.minute) + c.get(calendar.second)
        + ".png";
     //合成完整路径,注意 / 分隔符
     string string = path.getpath() + "/" + name;
     view.savetofile(string);
     toast.maketext(this, "保存成功!\n文件保存在:" + string, toast.length_long).show();
    } catch (filenotfoundexception e) {
     toast.maketext(this, "保存失败!\n" + e, toast.length_long).show();
    }
    break;
   }
  }
}

没什么难度,主要是将bitmap转png图片那里,找了一会发现 canvas 没有直接或间接保存的方法,刚好这里我使用了双缓冲,另一块画布的内容位图自己创建的,很自然想到将这个画布的位图保存为文件即可。

再查看 bitmap 有个 compress(compressformat format, int quality,outputstream stream) 方法,很明显将文件输出流传给这个方法就ok

 
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
@override
public void onclick(view v) {
  // todo auto-generated method stub
  switch (v.getid()) {
   case r.id.iv_btn_clear :
    view.clear();
    break;
   case r.id.iv_btn_save : {
    try {
     string sdstate = environment.getexternalstoragestate(); // 判断sd卡是否存在
     // 检查sd卡是否可用
     if (!sdstate.equals(android.os.environment.media_mounted)) {
      toast.maketext(this, "sd卡未准备好!", toast.length_short).show();
      break;
     }
     //获取系统图片存储路径
     file path = environment.getexternalstoragepublicdirectory(environment.directory_pictures);
     // make sure the pictures directory exists.
     path.mkdirs();
     //根据当前时间生成图片名称
     calendar c = calendar.getinstance();
     string name = ""
       + c.get(calendar.year) + c.get(calendar.month) + c.get(calendar.day_of_month)
       + c.get(calendar.hour_of_day) + c.get(calendar.minute) + c.get(calendar.second)
        + ".png";
     //合成完整路径,注意 / 分隔符
     string string = path.getpath() + "/" + name;
     view.savetofile(string);
     toast.maketext(this, "保存成功!\n文件保存在:" + string, toast.length_long).show();
    } catch (filenotfoundexception e) {
     toast.maketext(this, "保存失败!\n" + e, toast.length_long).show();
    }
    break;
   }
  }
}

完整实例代码点击此处本站下载

希望本文所述对大家android程序设计有所帮助。