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

来源:互联网 发布:贺银成网络课程 编辑:程序博客网 时间:2024/05/22 13:04

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

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

然后在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 stubif (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 blocke.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 stubinit();// 普通初始化initLinePpaint();}public SignView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubif (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 stubif (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);// 设置画笔风格}@Overridepublic 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;}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.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 blocke.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/";@Overrideprotected 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);}@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch(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";@Overrideprotected Parcelable onSaveInstanceState() {// TODO Auto-generated method stubfinal 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")@Overrideprotected void onRestoreInstanceState(Parcelable state) {// TODO Auto-generated method stubif (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 exceptionstate = null;}}



项目名称:SignViewDemo


1 0
原创粉丝点击