`
hbxflihua
  • 浏览: 682758 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Android 手写签名实例

阅读更多

  这篇文章本来想在一个月前就发布的,最近一直忙于国家电网手持终端的应用开发,所以没抽出时间来写。周末到了,终于可以闲下来整理整理。话不多说,直奔主题。

 

Android 提供了很多丰富、实用而且很有特色的功能。比如,语音识别、手写签名等等。本篇就为你介绍如何在android上进行个性化的手写签名。

 

首先大致说说需求:这是一个追求时尚、张扬个性的时代,我们希望在签名的地方,签名的是自己手写出来的很有个性的艺术字,而非根据手势识别出来的标准字体。

 

设计思路如下,在画板上进行签名(其实就是绘制图片),完成后保存为图片。然后将图片按照一定的比率进行缩放并显示在指定的位置。

 

这里给出一个实例,实例只是一个简单的例子,如有需要可以进行必要的扩展。这里我们需要一个Listener、一个Dialog、一个Activity这个三个java类。两个layout XML文件。

 

Listener很简单,主要是对手写板对话框的一个监听。

public interface DialogListener {
	
	public void refreshActivity(Object object);

}

 

 

接着是画板的Dialog

package cn.handwriting;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;


public class WritePadDialog extends Dialog {

	Context context;
	LayoutParams p ;
	DialogListener dialogListener;

	public WritePadDialog(Context context,DialogListener dialogListener) {
		super(context);
		this.context = context;
		this.dialogListener = dialogListener;
	}

	static final int BACKGROUND_COLOR = Color.WHITE;

	static final int BRUSH_COLOR = Color.BLACK;

	PaintView mView;

	/** The index of the current color to use. */
	int mColorIndex;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		requestWindowFeature(Window.FEATURE_PROGRESS);
		setContentView(R.layout.write_pad);
		
		p = getWindow().getAttributes();  //获取对话框当前的参数值   
		p.height = 320;//(int) (d.getHeight() * 0.4);   //高度设置为屏幕的0.4 
		p.width = 480;//(int) (d.getWidth() * 0.6);    //宽度设置为屏幕的0.6		   
		getWindow().setAttributes(p);     //设置生效
		
		
		mView = new PaintView(context);
		FrameLayout frameLayout = (FrameLayout) findViewById(R.id.tablet_view);
		frameLayout.addView(mView);
		mView.requestFocus();
		Button btnClear = (Button) findViewById(R.id.tablet_clear);
		btnClear.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				 mView.clear();
			}
		});

		Button btnOk = (Button) findViewById(R.id.tablet_ok);
		btnOk.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				try {
					dialogListener.refreshActivity(mView.getCachebBitmap());
					WritePadDialog.this.dismiss();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		
		Button btnCancel = (Button)findViewById(R.id.tablet_cancel);
		btnCancel.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				cancel();
			}
		});
	}
	

	/**
	 * This view implements the drawing canvas.
	 * 
	 * It handles all of the input events and drawing functions.
	 */
	class PaintView extends View {
		private Paint paint;
		private Canvas cacheCanvas;
		private Bitmap cachebBitmap;
		private Path path;

		public Bitmap getCachebBitmap() {
			return cachebBitmap;
		}

		public PaintView(Context context) {
			super(context);					
			init();			
		}

		private void init(){
			paint = new Paint();
			paint.setAntiAlias(true);
			paint.setStrokeWidth(3);
			paint.setStyle(Paint.Style.STROKE);
			paint.setColor(Color.BLACK);					
			path = new Path();
			cachebBitmap = Bitmap.createBitmap(p.width, (int)(p.height*0.8), Config.ARGB_8888);			
			cacheCanvas = new Canvas(cachebBitmap);
			cacheCanvas.drawColor(Color.WHITE);
		}
		public void clear() {
			if (cacheCanvas != null) {
				
				paint.setColor(BACKGROUND_COLOR);
				cacheCanvas.drawPaint(paint);
				paint.setColor(Color.BLACK);
				cacheCanvas.drawColor(Color.WHITE);
				invalidate();			
			}
		}

		
		
		@Override
		protected void onDraw(Canvas canvas) {
			// canvas.drawColor(BRUSH_COLOR);
			canvas.drawBitmap(cachebBitmap, 0, 0, null);
			canvas.drawPath(path, paint);
		}

		@Override
		protected void onSizeChanged(int w, int h, int oldw, int oldh) {
			
			int curW = cachebBitmap != null ? cachebBitmap.getWidth() : 0;
			int curH = cachebBitmap != null ? cachebBitmap.getHeight() : 0;
			if (curW >= w && curH >= h) {
				return;
			}

			if (curW < w)
				curW = w;
			if (curH < h)
				curH = h;

			Bitmap newBitmap = Bitmap.createBitmap(curW, curH, Bitmap.Config.ARGB_8888);
			Canvas newCanvas = new Canvas();
			newCanvas.setBitmap(newBitmap);
			if (cachebBitmap != null) {
				newCanvas.drawBitmap(cachebBitmap, 0, 0, null);
			}
			cachebBitmap = newBitmap;
			cacheCanvas = newCanvas;
		}

		private float cur_x, cur_y;

		@Override
		public boolean onTouchEvent(MotionEvent event) {
			
			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);
				break;
			}

			case MotionEvent.ACTION_MOVE: {
				path.quadTo(cur_x, cur_y, x, y);
				cur_x = x;
				cur_y = y;
				break;
			}

			case MotionEvent.ACTION_UP: {
				cacheCanvas.drawPath(path, paint);
				path.reset();
				break;
			}
			}

			invalidate();

			return true;
		}
	}

}

 

 

Activity是程序的入口,这个必不可少。

package cn.handwriting;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;

public class HandwritingActivity extends Activity {
    /** Called when the activity is first created. */
	
	private Bitmap mSignBitmap;
	private String signPath;
	private ImageView ivSign;
	private TextView tvSign;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setTitle("欢迎使用手写签名");
        ivSign =(ImageView)findViewById(R.id.iv_sign);
        tvSign = (TextView)findViewById(R.id.tv_sign);      
        
        ivSign.setOnClickListener(signListener);
        tvSign.setOnClickListener(signListener);
    }
    
	
	private OnClickListener signListener = new View.OnClickListener() {
		
		@Override
		public void onClick(View v) {
			WritePadDialog writeTabletDialog = new WritePadDialog(
					HandwritingActivity.this, new DialogListener() {
						@Override
						public void refreshActivity(Object object) {							
							
							mSignBitmap = (Bitmap) object;
							signPath = createFile();
							/*BitmapFactory.Options options = new BitmapFactory.Options();
							options.inSampleSize = 15;
							options.inTempStorage = new byte[5 * 1024];
							Bitmap zoombm = BitmapFactory.decodeFile(signPath, options);*/														
							ivSign.setImageBitmap(mSignBitmap);
							tvSign.setVisibility(View.GONE);
						}
					});
			writeTabletDialog.show();
		}
	};
	
	/**
	 * 创建手写签名文件
	 * 
	 * @return
	 */
	private String createFile() {
		ByteArrayOutputStream baos = null;
		String _path = null;
		try {
			String sign_dir = Environment.getExternalStorageDirectory() + File.separator;			
			_path = sign_dir + System.currentTimeMillis() + ".jpg";
			baos = new ByteArrayOutputStream();
			mSignBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
			byte[] photoBytes = baos.toByteArray();
			if (photoBytes != null) {
				new FileOutputStream(new File(_path)).write(photoBytes);
			}

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (baos != null)
					baos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return _path;
	}
}

 

 

对应的两个layout文件

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

 	<ImageView 
         android:id="@+id/iv_sign"
         android:layout_marginTop="50dp"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" 
         android:layout_gravity="center"
         />
 	
     <TextView
        android:id="@+id/tv_sign"
        android:layout_marginTop="50dp"
        android:layout_below="@id/iv_sign"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="点此签名"
        />	   
</LinearLayout>

 

 

write_pad.xml

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:greendroid="http://schemas.android.com/apk/res/com.cyrilmottier.android.gdcatalog"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/tablet_view"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" 
        android:background="@color/white">
    </FrameLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:drawable/bottom_bar"
        android:paddingTop="4dp" >

        <Button
            android:id="@+id/tablet_ok"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="确定" />
        
        <Button
            android:id="@+id/tablet_clear"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="清除" />

        <Button
            android:id="@+id/tablet_cancel"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="取消" />
    </LinearLayout>

</LinearLayout>

这里还有个样式的设置,所以在values下添加了一个colors.xml文件。具体参见样例。

 

7
0
分享到:
评论
13 楼 u013062349 2015-12-18  
  感谢
12 楼 qiuxue126com 2015-08-28  
写的很好,学习了,多谢!
11 楼 haichongsihao 2014-11-15  
楼主没有给写sd卡权限,所以不能保存
10 楼 x小旭x 2014-01-14  
感谢楼主分享,现在正需要这个功能
9 楼 whr0227 2013-10-23  
能不能加载上一次签批的图片,以便第二次进行修改
8 楼 trwhoya 2013-04-26  
hbxflihua 写道
chenjuanwangkai 写道
不能保存图片啊

HandwritingActivity 的 createFile()方法就是用来将图片保存到手持终端的啊。


是否要加<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7 楼 trwhoya 2013-04-26  
感觉楼主的资源!
6 楼 weilaidexiaoxuan 2013-02-25  
请问大侠,能不能在这基础上加个横纵坐标轴且提取签字的横纵坐标?求指导!!!
5 楼 tianshan20081 2012-09-12  
hbxflihua 写道
chenjuanwangkai 写道
不能保存图片啊

这个例子是我从公司的系统中剥离出来的,具体的应用根据具体情况而定。你可以根据这个例子来进行改造或进一步拓展,具体怎么用是你自己的事啦


感谢楼主啊!
是可以保存图片的!你给应用程序加上 存储设备的读写权限就 OK  啦!
4 楼 hbxflihua 2012-06-29  
chenjuanwangkai 写道
不能保存图片啊

这个例子是我从公司的系统中剥离出来的,具体的应用根据具体情况而定。你可以根据这个例子来进行改造或进一步拓展,具体怎么用是你自己的事啦
3 楼 hbxflihua 2012-06-29  
chenjuanwangkai 写道
不能保存图片啊

HandwritingActivity 的 createFile()方法就是用来将图片保存到手持终端的啊。
2 楼 chenjuanwangkai 2012-06-27  
不能保存图片啊
1 楼 14564187 2012-05-07  
感谢楼主 贡献好资源

相关推荐

    android mupdf droidtext0.5 PDF手写签名

    《Android Mupdf与Droidtext0.5:实现PDF手写签名技术详解》 PDF手写签名在当今数字化办公环境中扮演着至关重要的角色,它为电子文档提供了安全且便捷的签署方式。本文将深入探讨如何在Android平台上利用Mupdf库和...

    Android手写签名

    接下来,我们将详细探讨Android手写签名的相关知识点。 首先,我们需要了解Android绘图的基础。Android提供了`Canvas`类,它是Android图形系统的核心,允许开发者在`Bitmap`或`Surface`上进行绘制操作。在这个手写...

    Android电子签名手写板

    在Android平台上,开发一款电子签名手写板是一个常见的需求,特别是在移动支付、文档签署和表单填写等场景中。这个项目的核心目标是提供一个用户友好的界面,让用户能够通过触屏进行手写输入,然后将签名转换为图像...

    手写签名,可以保存图片,并页面显示TestDemo.

    总的来说,"手写签名,可以保存图片,并页面显示TestDemo"是一个结合了触摸输入、图像处理和前端展示技术的应用实例,它的核心是提供一种方便、直观且安全的方式来实现电子签名。通过这样的工具,用户能够在数字环境...

    Android实现手写签名

    本文实例为大家分享了Android手写签名的实现方法,产品要求用户可以在app上签协议。。所以得弄个手写签名版,参考了一些资料自己写了个PaintView去继承View,实现签名功能。 package com.****.*****.widget; import...

    android手写签名

    总之,通过设置`GestureOverlayView`的`fadeOffset`属性和在清除前临时调整这个值,我们可以实现Android手写签名功能,允许用户慢慢地写,支持多笔画,同时能迅速清除并重新书写。这种方法在需要用户现场签名的移动...

    Android 自定义View手写签名并保存图片功能

    本文主要介绍了如何使用 Android 自定义 View 实现手写签名并保存图片功能,并提供了详细的实例代码供大家参考。 一、自定义 View 的创建 在 Android 中,自定义 View 是指使用 Java 代码创建的 View 组件,该组件...

    android实现手写签名功能

    本文实例为大家分享了android手写签名展示的具体代码,供大家参考,具体内容如下 代码简单,就不发demo了,直接贴代码 package com.xx; import android.content.Context; import android.graphics.Bitmap; import ...

    android 手写签名

    一个手写签名 并生成jpg 格式的图片 的小例子 给大家分享一下

    [Android实例] 手写签名,画笔颜色选择器

    在Android开发中,实现手写签名并提供画笔颜色选择器是一项常见的需求,尤其是在移动应用中需要用户进行个性化操作或签署电子文档时。本实例将详细介绍如何在Android应用中集成这样的功能。 首先,我们需要创建一个...

    android自定义签名dialog

    这些库提供了方便的方法来绘制用户的手写签名,并保存为图片。在布局文件中引入签名视图,并在自定义Dialog类中初始化和设置相关参数。 4. **监听事件** 在`onCreateDialog()`方法中,设置按钮的点击事件监听器。...

    Android 画图/签名

    在Android平台上,开发人员可以利用Canvas和Bitmap等组件来实现丰富的图形绘制功能,包括但不限于画图、签名等交互式操作。Canvas是Android图形系统的核心部分,它提供了在内存中的Bitmap上绘制各种形状、线条和图像...

    Android电子手绘签名

    在Android开发中,电子手绘签名功能是一种常见的需求,它允许用户通过触摸屏或手写笔在屏幕上绘制签名,然后保存为图像。这个过程涉及到多个关键知识点,包括自定义View、Canvas绘图、图片保存以及文件操作。下面将...

    WriteSignTest.rar

    首先,Android手写签名通常涉及到以下几个技术点: 1. **画布(Canvas)与路径(Path)**:在Android中,画布是用于绘图的表面,而路径则用来描述图形的形状。手写签名的核心就是通过监听触屏事件,将用户的笔迹轨迹...

    Android实现签名涂鸦手写板

    本文实例为大家分享了Android实现签名涂鸦手写板的具体代码,供大家参考,具体内容如下 布局文件 &lt;?xml version=1.0 encoding=utf-8?&gt; &lt;LinearLayout xmlns:android=...

    Android编程实现的手写板和涂鸦功能

    总的来说,实现Android手写板和涂鸦功能需要结合Android的图形绘制API、用户事件处理以及数据存储机制。通过以上步骤,我们可以构建一个基本的涂鸦应用,让用户在手机或平板上自由地进行手写输入。

    AddImage_java_valuableufo_

    综上所述,"AddImage_java_valuableufo_"项目涵盖了Android开发中的图形绘制、触摸事件处理、图像处理、文件存储以及UI设计等多个重要知识点,是一个实用的安卓手写签名应用的实例。通过这个项目,开发者可以学习到...

    Tinker 热修复原理手写实现

    Tinker热修复技术是Android应用开发中的一项重要工具,通过深入理解其原理和手写实现,开发者可以更好地掌握热修复技术,提高应用的维护效率。尽管存在一些挑战,但随着技术的发展,这些问题也将逐步得到解决,让热...

    android-remote-digitizer:使用它作为手写板连接到PC

    对于开发者来说,这是一个学习移动设备与桌面设备间通信、以及手写输入处理的好实例;对于普通用户而言,这提供了一种新颖且实用的输入方式,尤其适合那些需要手写输入的场景,如设计、签名或者教学等。

Global site tag (gtag.js) - Google Analytics