手写签名板 android,Android 简易签名板

一个简单的练习,手写签名后,可以清空,保存,然后再相册进行查看

b8cff8d1d1a5

简易签名板

有5个知识点,需要注意:

在SignatureView的onTouchEvent()方法中,利用mPath.quadTo()方法,使绘制路径变得圆滑

在SignatureView的save()方法中,将View中的内容保存到一个Bitmap中

在SignatureView的closeStream()方法中,所有的读写流都实现了Closeable接口,可以用来关闭流

在SignatureView的clear()方法中,利用PorterDuff.Mode.CLEAR将Canvas中绘制的内容清空

在MainActivity中,图片保存到本地后,需要向系统发送一个广播,通知相册更新

1. SignatureView 控件

先通过mCanvas利用mPaint将绘制的路径保存进了mBitmap中,再将mBitmap在canvas绘制出来

public class SignatureView extends View {

private Paint mPaint;

private Path mPath;

private Canvas mCanvas;

private Bitmap mBitmap;

private float mLastX, mLastY;//上次的坐标

public SignatureView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

/***

* 初始化

*/

private void init() {

//关闭硬件加速

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

//画笔

mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);

mPaint.setStrokeWidth(5f);

mPaint.setColor(Color.parseColor("#FF4081"));

mPaint.setStyle(Paint.Style.STROKE);

mPaint.setStrokeJoin(Paint.Join.ROUND);//使画笔更加圆润

mPaint.setStrokeCap(Paint.Cap.ROUND);//同上

//路径

mPath = new Path();

//保存签名的画布

post(new Runnable() {//拿到控件的宽和高

@Override

public void run() {

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

mCanvas = new Canvas(mBitmap);

}

});

}

/**

* 绘制

*/

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if (mBitmap != null) {

canvas.drawColor(Color.WHITE);//绘制背景白色

drawSignaturePath(); //将路径绘制在mBitmap上

canvas.drawBitmap(mBitmap, 0, 0, null);//将mBitmap绘制在canvas上

}

}

/**

* 清空绘制内容

*/

public void clear() {

mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

mCanvas.drawPaint(mPaint);

mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));

mPath.reset();

invalidate();

}

/**

* 保存到指定的文件夹中

*/

public boolean save(String filePath) {

if (mBitmap != null && mLastY != 0f) {//没有绘制,就不保存

//从View中得到Bitmap

setDrawingCacheEnabled(true);

buildDrawingCache(true);

Bitmap bitmap = getDrawingCache(true);

//保存图片

File file = new File(filePath);

FileOutputStream fileOutputStream = null;

try {

fileOutputStream = new FileOutputStream(file);

if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)) {

fileOutputStream.flush();

return true;

}

} catch (java.io.IOException e) {

e.printStackTrace();

} finally {

closeStream(fileOutputStream);

}

}

return false;

}

/**

* 关闭流

*/

private void closeStream(Closeable closeable) {

if (closeable != null) {

try {

closeable.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 绘制签名

*/

private void drawSignaturePath() {

mCanvas.drawPath(mPath, mPaint);

}

/**

* 触摸事件 触摸绘制

*/

@Override

public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();

float x = event.getX();

float y = event.getY();

switch (action) {

case MotionEvent.ACTION_DOWN:

mLastX = x;

mLastY = y;

mPath.moveTo(mLastX, mLastY);

break;

case MotionEvent.ACTION_MOVE:

float dx = Math.abs(x - mLastX);

float dy = Math.abs(y - mLastY);

if (dx >= 3 || dy >= 3) {//绘制的最小距离 3px

//利用二阶贝塞尔曲线,使绘制路径更加圆滑

mPath.quadTo(mLastX, mLastY, (mLastX + x) / 2, (mLastY + y) / 2);

}

mLastX = x;

mLastY = y;

break;

case MotionEvent.ACTION_UP:

mPath.reset();

break;

}

invalidate();

return true;

}

/**

* 测量

*/

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int wSpecMode = MeasureSpec.getMode(widthMeasureSpec);

int wSpecSize = MeasureSpec.getSize(widthMeasureSpec);

int hSpecMode = MeasureSpec.getMode(heightMeasureSpec);

int hSpecSize = MeasureSpec.getSize(heightMeasureSpec);

if (wSpecMode == MeasureSpec.EXACTLY && hSpecMode == MeasureSpec.EXACTLY) {

setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);

} else if (wSpecMode == MeasureSpec.AT_MOST) {

setMeasuredDimension(200, hSpecSize);

} else if (hSpecMode == MeasureSpec.AT_MOST) {

setMeasuredDimension(wSpecSize, 200);

}

}

}

关键的地方都有注释

2.Activity 代码

在图片保存成功后,将图片的路径信息利用用广播发送给系统,通知相册更新

public class MainActivity extends AppCompatActivity {

private Button bt_clear,bt_save;

private SignatureView sv;

private final String APP_DIR = "com.signature.view";

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

init();

}

/**

* 初始化

*/

private void init() {

final String dir = Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+APP_DIR+File.separator;

final File fileDir = new File(dir);

if (!fileDir.exists()){

fileDir.mkdirs();

}

bt_clear = (Button) findViewById(R.id.bt_clear_main_activity);

sv = (SignatureView) findViewById(R.id.sv_main_activity);

bt_clear.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

sv.clear();

}

});

bt_save = (Button) findViewById(R.id.bt_save_main_activity);

bt_save.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

save(fileDir);

}

});

}

/**

* 保存图片

*/

private void save(File fileDir) {

final String filePath = getFilePath(fileDir);

if (sv.save(filePath)){//保存成功

//发送广播 通知系统相册更新

Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);

Uri uri = Uri.fromFile(new File(filePath));

intent.setData(uri);

sendBroadcast(intent);

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

}

}

/**

* 得到图片的路径 以及图片的名字

*/

private String getFilePath(File fileDir) {

SimpleDateFormat simpleDateFormat = (SimpleDateFormat) DateFormat.getDateTimeInstance();

final String fileName = simpleDateFormat.format(new Date())+".png";

Log.e("filename","---"+fileName);

File file = new File(fileDir,fileName);

return file.getAbsolutePath();

}

}

DateFormat.getDateTimeInstance()这个方法很方便的拿到手机设置的时间显示格式

布局文件:

android:id="@+id/activity_main"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/sv_main_activity"

android:layout_width="match_parent"

android:layout_height="400dp" />

android:id="@+id/bt_clear_main_activity"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@+id/sv_main_activity"

android:layout_marginStart="50dp"

android:text="清空"/>

android:id="@+id/bt_save_main_activity"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@+id/sv_main_activity"

android:layout_alignParentEnd="true"

android:layout_marginEnd="50dp"

android:text="保存" />

布局很简陋

3. 最后

主要是练习一下,复习最近一段学习到的一些知识

共勉 : )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android 手写签名是指使用手指在 Android 设备上绘制的签名。它通常用于数字签名或签署电子文件。可以通过使用手写输入 API 和触摸事件 API 来实现手写签名功能。这可以通过开发自定义视图或使用第三方库实现。 ### 回答2: 在Android设备上,可以使用手写签名的功能来实现电子签名的操作。通常情况下,手写签名是在触摸屏上进行操作,以模拟在纸上书写签名的效果。 要在Android上实现手写签名,首先需要创建一个画布,即一个可以进行绘制操作的区域。可以通过在布局文件中添加一个View组件,并设置其为画布来实现这一操作。 然后,需要实现手写的功能。可以通过在画布上监听触摸事件,当用户按下手指时,开始绘制手写轨迹;当用户抬起手指时,停止绘制。在绘制过程中,可以根据手指的运动轨迹来实时更新画布上的绘制内容,从而实现手写签名的效果。 除了手写功能,还可以为手写签名添加其他的交互功能。例如,可以在签名过程中撤销上一次绘制,或者清除整个签名区域。还可以实现对签名进行保存、导出和分享的功能,使得签名可以方便地进行后续处理或发送给他人。 在实际应用中,手写签名功能可以被广泛应用于各种场景。例如在线表单填写、合同签署、电子白等等。通过手写签名,可以实现更加便捷和高效的电子签名流程,有效地简化和加速工作和生活中的各种签名操作。 总之,在Android设备上,手写签名功能可以通过创建画布,监听触摸事件来实现,为用户提供一种方便、高效的电子签名方式。 ### 回答3: 在Android系统中,我们可以通过一些方法实现手写签名的功能。首先,我们可以利用触摸屏幕的功能来实现手写签名。用户在屏幕上使用手指或者触摸笔进行书写,我们可以通过监听屏幕上触摸的坐标和动作,来获取用户的手写签名数据。 其次,我们可以利用Android系统中提供的画布(Canvas)和绘图工具(Paint)来实现手写签名。我们可以创建一个可以在屏幕上绘制的画布,并获取用户手写签名操作,然后通过绘图工具在画布上进行绘制。这样就可以实现手写签名的效果。 另外,我们还可以借助一些第三方的手写签名库来实现手写签名功能。这些库可以提供更加丰富的手写签名功能,例如手写笔触的粗细、颜色选择、橡皮擦功能等。通过使用这些库,我们可以更加方便地实现手写签名的功能。 总结来说,Android系统中实现手写签名的方式可以包括触摸屏幕的监听、利用画布和绘图工具进行绘制,以及使用第三方手写签名库等。通过这些方法,我们可以在Android应用中实现手写签名的功能,满足用户在移动设备上进行签名的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值