java 手写签名_Android 自定义View手写签名并保存图片

f1ca4249eef5ab72a5cb9ce0cab87981.gif

GIF压缩有问题,运行很顺滑!!!

1.自定义View——支持设置画笔颜色,画笔宽度,画板颜色,清除画板,检查是否有签名,保存画板图片(复制粘贴可直接使用)

/*** Created by YyyyQ on 2020/3/5.

* 电子签名*/

public class SignatureView extendsView {privateContext context;//X轴起点

private floatx;//Y轴起点

private floaty;//画笔

private final Paint paint = newPaint();//路径

private final Path path = newPath();//画布

privateCanvas canvas;//生成的图片

privateBitmap bitmap;//画笔的宽度

private int paintWidth = 10;//签名颜色

private int paintColor =Color.BLACK;//背景颜色

private int backgroundColor =Color.WHITE;//是否已经签名

private boolean isTouched = false;//签名开始与结束

public interfaceTouch {void OnTouch(booleanisTouch);

}privateTouch touch;publicSignatureView(Context context) {super(context);

init(context);

}publicSignatureView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);

init(context);

}public SignatureView(Context context, @Nullable AttributeSet attrs, intdefStyleAttr) {super(context, attrs, defStyleAttr);

init(context);

}private voidinit(Context context) {this.context =context;//抗锯齿

paint.setAntiAlias(true);//样式

paint.setStyle(Paint.Style.STROKE);//画笔颜色

paint.setColor(paintColor);//画笔宽度

paint.setStrokeWidth(paintWidth);

}

@Overrideprotected void onSizeChanged(int w, int h, int oldw, intoldh) {super.onSizeChanged(w, h, oldw, oldh);//创建于view大小一致的bitmap

bitmap =Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

canvas= newCanvas(bitmap);

canvas.drawColor(backgroundColor);

isTouched= false;

}

@Overridepublic booleanonTouchEvent(MotionEvent event) {if (touch != null) touch.OnTouch(true);switch(event.getAction()) {//手指按下

caseMotionEvent.ACTION_DOWN:

touchDwon(event);break;//手指移动

caseMotionEvent.ACTION_MOVE:

isTouched= true;if (touch != null) touch.OnTouch(false);

touchMove(event);break;//手指抬起

caseMotionEvent.ACTION_UP:

canvas.drawPath(path, paint);

path.reset();break;

}//更新绘制

invalidate();return true;

}

@Overrideprotected voidonDraw(Canvas canvas) {super.onDraw(canvas);//画此次笔画之前的签名

canvas.drawBitmap(bitmap, 0, 0, paint);//通过画布绘制多点形成的图形

canvas.drawPath(path, paint);

}//手指按下的方法

private voidtouchDwon(MotionEvent event) {//重置绘制路径

path.reset();float downX =event.getX();float downY =event.getY();

x=downX;

y=downY;//绘制起点

path.moveTo(downX, downY);

}//手指滑动的方法

private voidtouchMove(MotionEvent event) {//当前的x,y坐标点

final float moveX =event.getX();final float moveY =event.getY();//之前的x,y坐标点

final float previousX =x;final float previousY =y;//获取绝对值

final float dx = Math.abs(moveX -previousX);final float dy = Math.abs(moveY -previousY);if (dx >= 3 || dy >= 3) {float cX = (moveX + previousX) / 2;float cY = (moveY + previousY) / 2;

path.quadTo(previousX, previousY, cX, cY);

x=moveX;

y=moveY;

}

}/*** 设置画笔颜色

*

*@parampaintColor*/

public void setPaintColor(intpaintColor) {this.paintColor =paintColor;

paint.setColor(paintColor);

}/*** 设置画笔宽度

*

*@parampaintWidth*/

public void setPaintWidth(intpaintWidth) {this.paintWidth =paintWidth;

paint.setStrokeWidth(paintWidth);

}/*** 设置画板颜色

*

*@paramcanvasColor*/

public void setCanvasColor(intcanvasColor) {this.backgroundColor =canvasColor;

}/*** 清除画板*/

public voidclear() {if (canvas != null) {

isTouched= false;//更新画板

paint.setColor(paintColor);

paint.setStrokeWidth(paintWidth);

canvas.drawColor(backgroundColor, PorterDuff.Mode.CLEAR);

invalidate();

}

}/*** 获取画板的Bitmap

*

*@return

*/

publicBitmap getBitmap() {

setDrawingCacheEnabled(true);

buildDrawingCache();

Bitmap bitmap=getDrawingCache();

setDrawingCacheEnabled(false);returnbitmap;

}/*** 是否有签名

*

*@return

*/

publicBoolean getSigstatus() {returnisTouched;

}/*** 保存画板

*

*@parampath 保存到路径*/@SuppressLint("WrongThread")public Boolean save(String path) throwsIOException {

Bitmap bitmap= this.bitmap;

ByteArrayOutputStream bos= newByteArrayOutputStream();

bitmap.compress(Bitmap.CompressFormat.PNG,100, bos);byte[] buffer =bos.toByteArray();if (buffer != null) {

File file= newFile(path);if(file.exists()) {

file.delete();

}

OutputStream outputStream= newFileOutputStream(file);

outputStream.write(buffer);

outputStream.close();return true;

}else{return false;

}

}

}

2.xml布局引用自定义View(注意包名)

android:id="@+id/signature"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="#fff" />

android:layout_width="match_parent"android:layout_height="50dp"android:layout_margin="20dp"android:orientation="horizontal">

android:id="@+id/clear"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="清除" />

android:id="@+id/isSignature"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginLeft="10dp"android:layout_weight="1"android:gravity="center"android:text="是否签名" />

android:id="@+id/save"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginLeft="10dp"android:layout_weight="1"android:gravity="center"android:text="保存" />

3.Activity调用

/**

* Created by YyyyQ on 2020/3/9.

*/

public class SignatureActivity extends AppCompatActivity {

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_signature);

SignatureView signatureView = findViewById(R.id.signature);

//设置画笔颜色(可以不设置--默认画笔宽度10,画笔颜色黑,背景颜色白)

signatureView.setPaintColor(Color.BLACK);

signatureView.setPaintWidth(20);

signatureView.setCanvasColor(Color.WHITE);

//清除

Button clear = findViewById(R.id.clear);

clear.setOnClickListener(view -> {

signatureView.clear();

//设置画笔颜色(可以不设置--默认画笔宽度10,画笔颜色黑,背景颜色白)

signatureView.setPaintColor(Color.BLACK);

signatureView.setPaintWidth(20);

signatureView.setCanvasColor(Color.WHITE);

});

//是否含有签名

Button isSignature = findViewById(R.id.isSignature);

isSignature.setOnClickListener(view -> {

if (signatureView.getSigstatus()) {

Toast.makeText(SignatureActivity.this, "有签名", Toast.LENGTH_SHORT).show();

} else {

Toast.makeText(SignatureActivity.this, "无签名", Toast.LENGTH_SHORT).show();

}

});

//保存

Button save = findViewById(R.id.save);

save.setOnClickListener(view -> {

try {

if (signatureView.save("/sdcard/YyyyQ.png")) {

Toast.makeText(SignatureActivity.this, "保存成功", Toast.LENGTH_SHORT).show();

} else {

Toast.makeText(SignatureActivity.this, "保存失败", Toast.LENGTH_SHORT).show();

}

} catch (IOException e) {

e.printStackTrace();

}

});

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/440518.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【2019第十届蓝桥杯省赛C/C++B组题解】(非官方题解)

A。 数数题。 答案:490 B。 26进制模拟。 答案:BYQ C。 类似fib数列求值,递推一下就好。 答案:4659 D。 注意两个坑点,一个是正整数,所以枚举要从1开始。第二个坑点是互不相同的,为了达到这…

java对象模型 指令_深入理解多线程(二)—— Java的对象模型

上一篇文章中简单介绍过synchronized关键字的方式,其中,同步代码块使用monitorenter和monitorexit两个指令实现,同步方法使用ACC_SYNCHRONIZED标记符实现。后面几篇文章会从JVM源码的角度更加深入,层层剥开synchronized的面纱。在…

java 学生课程成绩_Java课设--学生成绩管理系统一

写在前面这个项目是Java课程的课设,一共花了5天的时间去完成它,在这期间感谢一些博主的帮助,让我了解到了一些新的技术知识,所以打算写这一系列博客来介绍一整个课设项目,也为了帮助之后的人,如有错误&…

java调用cplex案例_【CPLEX教程03】java调用cplex求解一个TSP问题模型

前面我们已经搭建好cplex的java环境了,相信大家已经跃跃欲试,想动手写几个模型了。今天就来拿一个TSP的问题模型来给大家演示一下吧~CPLEX系列教程可以关注我们的公众号哦!获取更多精彩消息!01 TSP寤烘ā关于TSP建模,就…

java 自动启动监听_Spring Boot 启动事件和监听器,太强大了!

大家都知道,在 Spring 框架中事件和监听无处不在,打通了 Spring 框架的任督二脉,事件和监听也是 Spring 框架必学的核心知识之一。一般来说,我们很少会使用到应用程序事件,但我们也不要忘了它们的存在,比如…

java day_Java_Day7(上)

Java learning_Day7(上)内容常用类枚举类型常用类String 类java.lang.String 类代表不可变的字符序列。String 类的常见构造方法:String(String original)创建一个 String 对象为 original 的拷贝。String(char[] value)用一个字符数组创建一个 String 对象。String…

java关键字 valotile_Java内存模型-jsr133规范介绍,java中volatile关键字的含义

最近在看《深入理解Java虚拟机:JVM高级特性与最佳实践》讲到了线程相关的细节知识,里面讲述了关于java内存模型,也就是jsr 133定义的规范。系统的看了jsr 133规范的前面几个章节的内容,觉得受益匪浅。废话不说,简要的介…

Java重载和重写6_深入理解Java中的重写和重载

深入理解Java中的重写和重载重载(Overloading)和重写(Overriding)是Java中两个比较重要的概念。但是对于新手来说也比较容易混淆。本文通过两个简单的例子说明了他们之间的区别。定义重载简单说,就是函数或者方法有同样的名称,但是参数列表不相同的情形&…

python 协程池gevent.pool_进程池\线程池,协程,gevent

目录1. 进程池与线程池2. 协程3. gevent4. 单线程下实现并发的套接字通信首先写一个基于多线程的套接字服务端:from socket import *from threading import Threaddef comunicate(conn):while True: # 通信循环try:data conn.recv(1024)if len(data) 0: breakconn.send(data.…

java poi 3.13_Java 读取Excl文件 (poi-3.13)

最近做项目遇到了读取Excel数据到数据库做数据的初始化。于是找一个。发现(poi-3.13)可以解决问题。可以解析两种格式(xlsx和xls)以下是实现的步骤1.下载poi3.13包,地址(http://poi.apache.org/download.html#POI-3.13)2.学习APi。接下来是还是demo来说明问题吧&…

【CodeChef - CLIQUED 】Bear and Clique Distances(建图,缩点技巧,思维)

题干: 解题报告: 主要就是在于怎么处理那个前K个点:组成一个团。换句话说,缩成一个点。先直接当成每个点多了k条边来处理,T了。想想也是啊,要是K1e5,那就是1e10条边了。。刚开始尝试了半天缩点&…

【HDU - 5649】DZY Loves Sorting(线段树,区间更新区间查询,思维,01缩数变换,线段树分割)

题干: DZY has a sequence a[1..n]a[1..n]. It is a permutation of integers 1∼n1∼n. Now he wants to perform two types of operations: 0lr0lr: Sort a[l..r]a[l..r] in increasing order. 1lr1lr: Sort a[l..r]a[l..r] in decreasing order. After doin…

php错误403_phpstudy访问文件报错403/Forbidden解决办法

使用phpstudy访问WWW目录下的文件时,浏览器提示Forbidden错误,没有访问权限。我在网上搜索了喝多资料以及本人亲自尝试过后,总结了一下两种方法。方法一:打开phpStudy,点击按键“其他选项菜单”>找到phpStudy配置&g…

【CodeForces - 294B】Shaass and Bookshelf(枚举,贪心,思维,组内贪心组间dp)

题干: Shaass has n books. He wants to make a bookshelf for all his books. He wants the bookshelfs dimensions to be as small as possible. The thickness of the i-th book is ti and its pages width is equal to wi. The thickness of each book is eith…

mac php开发集成环境,MAC OS X下php集成开发环境mamp

之前苦于mac上搭建本地服务器之艰辛,找寻好久都没找到一款类似windows上集成的本地服务器环境,诸如phpstudy,xampp,appserv,虽说xampp也有mac版,但不知为何不是Apache启动不了,这里小编为大家分享了MAC OS X 下php集成…

php获取手机目录,php如何获取手机型号

手机App中判断平台,可以根据$_SERVER[HTTP_USER_AGENT]中的内容来判断浏览器类型或手机平台。(推荐学习:PHP编程从入门到精通)iPhone UA:Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, l…

【CodeForces - 920E】Connected Components? (dsu,补图连通块,STLset+map,bfs 或bitset)

题干: You are given an undirected graph consisting of n vertices and edges. Instead of giving you the edges that exist in the graph, we give you m unordered pairs (x, y) such that there is no edge between x and y, and if some pair of vertices…

【牛客 - 551F】CSL 的神奇序列(推公式,猜结论,母函数)

题干: 链接:https://ac.nowcoder.com/acm/contest/551/F 来源:牛客网 题目描述 CSL 有一个神奇的无穷实数序列,他的每一项满足如下关系: 对于任意的正整数 n ,有 , 并且 。 CSL 很清楚这样的序列是唯…

java什么时候创建进程,Java创建进程

Java创建进程1 进程的概念 11.1 进程的概念 11.2 进程的特征 11.3 进程与线程区别 12 进程的创建 12.1 JAVA进程的创建 12.1.1 ProcessBuilder 22.1.2 Runtime 32.1.3 Process 42.2 实例 52.2.1 创建子进程 52.2.2 进程阻塞问题 72.2.3 在java中执行java程序 111 进程的概念1.1…

【牛客 - 157E】青蛙(floyd最短路,建图)

题干: 链接:https://ac.nowcoder.com/acm/contest/157/E 来源:牛客网 题目描述 有一只可爱的老青蛙,在路的另一端发现了一个黑的东西,想过去一探究竟。于是便开始踏上了旅途 一直这个小路上有很多的隧道&#xff0…