首页 > 系统 > Android > 正文

Android 自定义View-->电子签名

2019-11-09 18:43:28
字体:
来源:转载
供稿:网友

电子签名的作用:记录用户在设备上输入的信息,然后在本地保存图片。

首先在构造方法中初始化画笔和笔迹集合,画笔的属性主要有颜色、宽度、起始和结束的图形、拐角弧度和风格。笔迹集合方便客户多笔迹输入。

然后在onTouchEvent方法中使用Path类来记录用户接触设备并在设备上移动的痕迹,当用户接触设备就把当前的Path添加到笔迹集合中去,当用户移动的时候就刷新当前Path的路径。

最后使用onDraw方法将Canvas(画布)保存的笔迹绘制出来。

为了方便外界修改画笔的颜色和宽度,这里开放两个接口供外界调用,有两种方式:1、在代码中调用组件的set方法,可以在任意时候设置画笔属性;2、在xml文件中静态指定画笔的颜色和宽度,通过如下代码设置:

<resources>    <declare-styleable name="SignView">        <attr name="lineColor" format="color"/>        <attr name="lineWidth" format="dimension"/>    </declare-styleable></resources> 

然后在SignView的构造方法中获取在xml中设置的属性

public SignView(Context context, AttributeSet attrs) {		super(context, attrs);		// TODO Auto-generated constructor stub		if (attrs != null) {			TypedArray a = context.obtainStyledAttributes(attrs,					R.styleable.SignView);			parseTyepdArray(a);		}		init();// 普通初始化		initLinePpaint();	}PRivate void parseTyepdArray(TypedArray a) {		lineColor = a.getColor(styleable.SignView_lineColor, Color.RED);		lineWidth = a.getDimension(styleable.SignView_lineWidth, 25);		a.recycle();	}

这样我们就能在xml文件中使用自定义的属性了

<com.example.signviewdemo.SignView         android:id="@+id/signView"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_weight="4"        android:background="@android:color/white"        app:lineColor="@android:color/holo_orange_dark"        app:lineWidth="10dp"        />

这里需要在布局文件的根节点定义app属性,只需要添加xmlns:app="http://schemas.android.com/apk/res-auto"即可。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.signviewdemo.MainActivity"     android:orientation="vertical"    android:background="@android:color/darker_gray"    >接下来实现清空输入的笔迹

/**	 * 清空输入	 */	public void clearPath() {		lines.removeAll(lines);		invalidate();	}

最后将整个View以图片的形式保存到本地

/**	 * 将图片保存到文件	 */	public boolean saveImageToFile(String filePath) {		try {			File file = new File(filePath);			if (!file.exists()) {				file.mkdirs();			}			String localFile=file.getAbsolutePath()+"/"+System.currentTimeMillis()+".png";			File f=new File(localFile);						FileOutputStream fos=new FileOutputStream(f);			getImage().compress(CompressFormat.PNG, 100, fos);			fos.flush();			fos.close();			return true;		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();			return false;		}	}	/**	 * 将View保存为Bitmap	 */	public Bitmap getImage() {		Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),				Config.RGB_565);		Canvas canvas = new Canvas(bitmap);		// 绘制背景		Drawable bgDrawable = getBackground();		if (bgDrawable != null) {			bgDrawable.draw(canvas);		} else {			canvas.drawColor(Color.WHITE);		}		// 绘制View视图内容		draw(canvas);		return bitmap;	}SingView的完整代码:

public class SignView extends View {	private Paint linePaint;// 画笔	private ArrayList<Path> lines;// 写字的笔迹,支持多笔画	private int lineCount;// 记录笔画数目	private final int DEFAULT_LINE_WIDTH = 10;// 默认笔画宽度	private int lineColor = Color.BLACK;// 默认字迹颜色(黑色)	private float lineWidth = DEFAULT_LINE_WIDTH;// 笔画宽度	public SignView(Context context) {		super(context);		// TODO Auto-generated constructor stub		init();// 普通初始化		initLinePpaint();	}	public SignView(Context context, AttributeSet attrs) {		super(context, attrs);		// TODO Auto-generated constructor stub		if (attrs != null) {			TypedArray a = context.obtainStyledAttributes(attrs,					R.styleable.SignView);			parseTyepdArray(a);		}		init();// 普通初始化		initLinePpaint();	}	public SignView(Context context, AttributeSet attrs, int defStyleAttr) {		super(context, attrs, defStyleAttr);		// TODO Auto-generated constructor stub		if (attrs != null) {			TypedArray a = context.obtainStyledAttributes(attrs,					R.styleable.SignView);			parseTyepdArray(a);		}		init();// 普通初始化		initLinePpaint();	}	private void parseTyepdArray(TypedArray a) {		lineColor = a.getColor(styleable.SignView_lineColor, Color.RED);		lineWidth = a.getDimension(styleable.SignView_lineWidth, 25);		a.recycle();	}	private void init() {		lines = new ArrayList<Path>();	}	/**	 * 初始化画笔	 */	private void initLinePpaint() {		linePaint = new Paint();		linePaint.setColor(lineColor);// 画笔颜色		linePaint.setStrokeWidth(lineWidth);// 画笔宽度		linePaint.setStrokeCap(Cap.ROUND);// 设置笔迹的起始、结束为圆形		linePaint.setPathEffect(new CornerPathEffect(50));// PahtEfect指笔迹的风格,CornerPathEffect在拐角处添加弧度,弧度半径50像素点		linePaint.setStyle(Style.STROKE);// 设置画笔风格	}	@Override	public boolean onTouchEvent(MotionEvent event) {		// TODO Auto-generated method stub		/**		 * 考虑到这个view会出现在lib工程里,因此使用if else		 */		if (event.getAction() == MotionEvent.ACTION_DOWN) {			Path path = new Path();			path.moveTo(event.getX(), event.getY());			lines.add(path);			lineCount = lines.size();		} else if (event.getAction() == MotionEvent.ACTION_MOVE) {			lines.get(lineCount - 1).lineTo(event.getX(), event.getY());			invalidate();		} else {		}		return true;	}	@Override	protected void onDraw(Canvas canvas) {		// TODO Auto-generated method stub		super.onDraw(canvas);		if (lines != null && lines.size() > 0) {			for (Path path : lines) {				canvas.drawPath(path, linePaint);			}		}	}	// 开放设置画笔颜色和宽度的接口	/**	 * 开放设置画笔颜色的接口	 * 	 * @param lineColor	 */	public void setLineColor(int lineColor) {		this.lineColor = lineColor;		linePaint.setColor(lineColor);	}	/**	 * 开放设置画笔宽度的接口	 * 	 * @param lineWidth	 */	public void setLineWidth(float lineWidth) {		this.lineWidth = lineWidth;		linePaint.setStrokeWidth(lineWidth);	}	/**	 * 清空输入	 */	public void clearPath() {		lines.removeAll(lines);		invalidate();	}	/**	 * 将图片保存到文件	 */	public boolean saveImageToFile(String filePath) {		try {			File file = new File(filePath);			if (!file.exists()) {				file.mkdirs();			}			String localFile=file.getAbsolutePath()+"/"+System.currentTimeMillis()+".png";			File f=new File(localFile);						FileOutputStream fos=new FileOutputStream(f);			getImage().compress(CompressFormat.PNG, 100, fos);			fos.flush();			fos.close();			return true;		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();			return false;		}	}	/**	 * 将View保存为Bitmap	 */	public Bitmap getImage() {		Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),				Config.RGB_565);		Canvas canvas = new Canvas(bitmap);		// 绘制背景		Drawable bgDrawable = getBackground();		if (bgDrawable != null) {			bgDrawable.draw(canvas);		} else {			canvas.drawColor(Color.WHITE);		}		// 绘制View视图内容		draw(canvas);		return bitmap;	}}

MainActivity

public class MainActivity extends Activity implements OnClickListener{	private SignView signView;	private Button btn_clear;	private Button btn_save;		private static final String SAVE_PATH=Environment.getExternalStorageDirectory()+"/SignViewDemo/";			@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_main);		signView=(SignView) findViewById(R.id.signView);		btn_clear=(Button) findViewById(R.id.btn_clear);		btn_save=(Button) findViewById(R.id.btn_save);		btn_clear.setOnClickListener(this);		btn_save.setOnClickListener(this);//		signView.setLineColor(Color.BLUE);//		signView.setLineWidth(20);	}	@Override	public void onClick(View v) {		// TODO Auto-generated method stub		switch(v.getId()){		case R.id.btn_clear:			signView.clearPath();			break;		case R.id.btn_save:			if(signView.saveImageToFile(SAVE_PATH)){				Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT).show();			}else{				Toast.makeText(MainActivity.this, "保存失败", Toast.LENGTH_SHORT).show();			}			break;		}	}}

==============2017年2月7日更新=============

添加翻转设备,不会清除内容的功能

//实现设备翻转,数据不会被清除	private static final String INSTANCE_STATE = "saved_instance";	private static final String LINE_COLOR = "line_color";	private static final String LINE_WIDTH = "line_width";	private static final String LINES = "lines";	@Override	protected Parcelable onSaveInstanceState() {		// TODO Auto-generated method stub		final Bundle bundle = new Bundle();		Parcelable superState=super.onSaveInstanceState();		bundle.putParcelable(INSTANCE_STATE, superState);		bundle.putInt(LINE_COLOR, getLineColor());		bundle.putFloat(LINE_WIDTH, getLineWidth());		bundle.putSerializable(LINES, lines);		return bundle;	}	@SuppressWarnings("unchecked")	@Override	protected void onRestoreInstanceState(Parcelable state) {		// TODO Auto-generated method stub		if (state instanceof Bundle) {			final Bundle bundle = (Bundle) state;			lineColor = bundle.getInt(LINE_COLOR);			lineWidth = bundle.getFloat(LINE_WIDTH);			lines=(ArrayList<Path>) bundle.getSerializable(LINES);		}		try {			super.onRestoreInstanceState(state);		} catch (Exception e) {			// TODO: handle exception			state = null;		}	}

项目名称:SignViewDemo


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表