- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Android编程实现手绘及保存为图片的方法(附demo源码下载)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
本文实例讲述了android编程实现手绘及保存为图片的方法。分享给大家供大家参考,具体如下:
运行效果图预览:
应 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程序设计有所帮助.
最后此篇关于Android编程实现手绘及保存为图片的方法(附demo源码下载)的文章就讲到这里了,如果你想了解更多关于Android编程实现手绘及保存为图片的方法(附demo源码下载)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
十,Spring Boot 的内容协商的详细剖析(附+Debug调试说明) @ 目录 十,Spring Boot 的内容协商的详细剖析(附+Debug调试说明) 1. 基本
八,SpringBoot Web 开发访问静态资源(附+详细源码剖析) @ 目录 八,SpringBoot Web 开发访问静态资源(附+详细源码剖析) 1. 基本介绍
在sql语句执行前 DB::enableQueryLog(); sql sql sql sql sql dd(DB::getQueryLog()); ?
本文实例讲述了PHP global全局变量的使用与注意事项。分享给大家供大家参考,具体如下: 使用global在方法里面声明外部变量为全局变量,即可以调用该变量。 示例1. global基本用法
SSO简介 定义: 传统的单站点登录访问授权机制是:登录成功后将用户信息保存在session中,sessionId保存在cookie中,每次访问需要登录访问的资源(url)时判断当前sessio
性能测试,在编写代码后,单元测试及性能测试是重要的验收点,好的性能测试可以让我们提前发现程序中存在的问题。 测试用例 在Rust中,测试通常有两部分,一部分是文档测试,一部分是模块测试。 通常我们
我正在制作一个非常简单的应用程序,它有一个输入框和一个按钮。 Input 用于输入email 使用事件处理器订阅按钮 输入电子邮件并点击按钮将进行 api 调用,(此方法有效) subscribe
我正在制作一个非常简单的应用程序,它有一个输入框和一个按钮。 Input 用于输入email 使用事件处理器订阅按钮 输入电子邮件并点击按钮将进行 api 调用,(此方法有效) subscribe
一个星期以来,我一直在努力寻找如何做到这一点,但一直无法做到。我的 html 导航栏看起来像这样。
我们经常在程序设计中用到的数组,同样在脚本中很常用。本节就详细介绍一下数组,以及哈希表在PowerShell中的使用。 数组 在PowerShell中,声明一个变量为数组时,需要使用符号&quo
方法一:先查询出所有记录,然后在逻辑层转化为拼音首字母后查询,显然傻瓜才会这么做。 方法二:在需要搜索的表中添加一个字段用于存放被检索字段内容对应的拼音,在搜索的时候同时去查询这两个字
intellij idea2021是一款java开发神器,功能丰富好用,本文提供其安装包、破解版、补丁、绿色版、激活码等下载,手把手教大家完美安全永久安装破解,亲测绝对可以永久激活。 此方法支持所有的
我在构建一个网站时遇到了一个问题,即我的 h1 内容与我的导航栏重叠。我在 css 中使用了 margin-top 标签,但它不起作用。
前言 时隔2年.(PS:其实陆陆续续在优化,不过没发博客).. .本组件又迎来了新的更新... 很久没更新博客了.生了娃,换了工作单位,太忙了..实在抱歉 NE
为什么 CLGeocoder reverseGeocodeLocation 在查找地址时返回具有不同纬度/经度的地标? 背景:就用户在 map 上“长按”以放置图钉而言,但我的代码对此进行了反向地理编
我是一名优秀的程序员,十分优秀!