android 仿qq手写板涂鸦
时间:2022-04-24
本文章向大家介绍android 仿qq手写板涂鸦,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
以前博客的链接:点击打开链接
附上关键代码:
MainView.java
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 代码:
@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
@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;
}
}
}
- 联系生活来简化sql(r3笔记第43天)
- [笔记]使用Python一步一步地来进行数据分析
- 使用 R 语言从拉勾网看数据挖掘岗位现状
- 使用strace分析exp的奇怪问题(r3笔记第41天)
- Python文本挖掘:知乎网友如何评价《人民的名义》
- 怎样做中文文本的情感分析?
- 由一条日志警告所做的调优分析(r3笔记第40天)
- 生产环境sql语句调优实战第十篇(r3笔记第39天)
- memory_target设置不当导致数据库无法启动的问题(r3笔记第38天)
- python利用结巴分词做新闻地图
- 数据库静默安装总结(r3笔记第58天)
- 用TensorFlow实现文本分析模型,做个聊天机器人
- 深度学习:用tensorflow建立线性回归模型
- 用python基于2015-2016年的NBA常规赛及季后赛的统计数据分析
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- SAP CDS view的日期格式转换,比如从YYYYMMDD转到DD/MM/YYYY
- SAP CDS view如何取得当前系统日期和系统时间戳
- Vue 父组件如何监听子组件的生命周期
- Django3+websocket+paramiko实现web页面实时输出
- 【5分钟玩转Lighthouse】开车也能跑程序
- LeetCode74|有序矩阵中第K小的元素
- LeetCode73|根据字符出现频率排序
- LeetCode72|前K个高频元素
- LeetCode71|数组中第K个最大元素
- LeetCode70|最小K个数
- LeetCode69|消失的数字
- LeetCode68|和为s的两个数字
- LeetCode78|存在重复元素
- LeetCode77|排序链表
- LeetCode76|两颗二叉搜索树中的所有元素