Android UI设计系列之自定义DrawView组件实现数字签名效果(5)


最近项目中有个新的需求,用户在完交易需要进行输入支付密码付款的时候,要让用户签下自己的签名,提起到数字签名这个东西,感觉有点高大上,后来想想数字签名的原理也不是太复杂,主要实现原理就是利用了View的绘图原理,把用户在屏幕上的手指移动轨迹显示在屏幕上,接着把在屏幕上显示的轨迹View转换成一张图片,最后把图片保存到本地或者上传到服务器...
还是老规矩,首先看一下工程目录吧:

public class DrawView extends View { 
 
 /** 
  * 签名画笔 
  */ 
 private Paint paint; 
 /** 
  * 签名画布 
  */ 
 private Canvas cacheCanvas; 
 /** 
  * 画笔路径 
  */ 
 private Path path; 
 /** 
  * 缓存图片 
  */ 
 private Bitmap cacheBitmap; 
 /** 
  * 图片宽度 
  */ 
 private int width; 
 /** 
  * 图片高度 
  */ 
 private int height; 
 /** 
  * 手指触摸屏幕时的X,Y坐标 
  */ 
 private float xDown, yDown; 
 /** 
  * 是否正在绘制 
  */ 
 private boolean isDrawing = false; 
 
 /** 
  * 默认画笔颜色 
  */ 
 private int paintColor = Color.CYAN; 
 
 /** 
  * 默认画板背景色 
  */ 
 private int canvasColor = Color.parseColor("#bbccaa"); 
 
 public DrawView(Context context, int width, int height) { 
  super(context); 
  this.width = width; 
  this.height = height; 
  initWedgits(); 
 } 
 
 /** 
  * 初始化组件 
  */ 
 private void initWedgits() { 
  try { 
   paint = new Paint(Paint.DITHER_FLAG); 
   // 设置抗锯齿 
   paint.setAntiAlias(true); 
   // 设置画笔宽度 
   paint.setStrokeWidth(3); 
   paint.setDither(true); 
   // 设置样式 
   paint.setStyle(Paint.Style.STROKE); 
   paint.setStrokeJoin(Paint.Join.ROUND); 
   paint.setStrokeCap(Paint.Cap.ROUND); 
   // 画笔颜色 
   paint.setColor(paintColor); 
   // 绘制路径 
   path = new Path(); 
   // 创建空缓存图片 
   cacheBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); 
   // 把画布内容画到空缓存图片上 
   cacheCanvas = new Canvas(cacheBitmap); 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
  
 @Override 
 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
  super.onSizeChanged(w, h, oldw, oldh); 
 } 
 
 @Override 
 protected void onDraw(Canvas canvas) { 
  super.onDraw(canvas); 
 
  canvas.drawColor(canvasColor); 
  canvas.drawBitmap(cacheBitmap, 0, 0, paint); 
  canvas.drawPath(path, paint); 
 } 
 
 @Override 
 public boolean onTouchEvent(MotionEvent event) { 
  // 记录手指摁下屏幕时的X坐标 
  final float x = event.getX(); 
  // 记录手指摁下屏幕时的Y坐标 
  final float y = event.getY(); 
  switch (event.getAction()) { 
  case MotionEvent.ACTION_DOWN: 
   // 手指摁下时清空之前的设置 
   path.reset(); 
   // 设置路径起始点 
   path.moveTo(x, y); 
   xDown = x; 
   yDown = y; 
   isDrawing = true; 
   break; 
  case MotionEvent.ACTION_MOVE: 
   // 移动下一点 
   path.quadTo(xDown, yDown, x, y); 
   // 重新设置起点 
   xDown = x; 
   yDown = y; 
   isDrawing = true; 
   break; 
  case MotionEvent.ACTION_UP: 
   path.lineTo(xDown, yDown); 
   // 手指抬起时绘制路径 
   cacheCanvas.drawPath(path, paint); 
   // 路径重置 
   path.reset(); 
   isDrawing = false; 
   break; 
  default: 
   break; 
  } 
  // 刷新界面 
  invalidate(); 
  return true; 
 } 
 
 /** 
  * 设置画笔颜色 
  * 
  * @param color 
  *   画笔颜色 
  */ 
 public void setPaintColor(int color) { 
  paintColor = color; 
 } 
 
 /** 
  * 设置画板颜色 
  * 
  * @param color 
  *   画板颜色 
  */ 
 public void setCanvasColor(int color) { 
  canvasColor = color; 
 } 
 
 /** 
  * 返回绘画状态 
  * 
  * @return【true:正在绘制】【false:绘制完成】 
  */ 
 public boolean getDrawState() { 
  return isDrawing; 
 } 
 
 /** 
  * 返回Bitmap 
  * 
  * @return 返回绘制的图片 
  */ 
 public Bitmap getBitmap() { 
  return cacheBitmap; 
 } 
} 

DrawView的代码注释都很清晰,我还是大致说下DrawView的执行逻辑吧,DrawView继承了View也就是说具有了View的所有功能,要实现图片绘制就要实现onDraw()方法,要实现对手指在屏幕上的轨迹绘制就需要获取轨迹坐标,所以需要重写onTouchEvent()放法,重点在onTouchEvent()方法中。当手指摁下时我们绘制起点,但是在绘制起点前需要先调用path.reset()方法,防止path进行二次重绘,path的moveTo方法就是来绘制当前触摸事件的起点,摁下完成之后调用inValidate()方法进行界面刷新。当手指移动时调用path.quadTo()方法,这个方法就是追加的意思,把新坐标点追加到path中,手指移动之后再调用inValidate()方法进行界面刷新,最后当手指抬起时,把在当前事件周期内的轨迹绘制到画板cacheCanvas上,最后再调用inValidate()方法进行界面刷新,因此一次的手指移动轨迹就绘制完成,当要进行下一次的绘制,就是重复以上操作了...

接下来我们看看DrawView的使用吧,首先看一下布局文件:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
 xmlns:android="http://schemas.android.com/apk/res/android" 
 android:orientation="vertical" 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" 
 android:background="#ffffff"> 
 
 <TextView 
  android:id="@+id/title" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:text="请绘制签名" 
  android:textSize="18sp" 
  android:layout_margin="5dip" 
  android:gravity="center" 
  android:textColor="#000000" /> 
 
 <FrameLayout 
  android:id="@+id/contents" 
  android:layout_width="fill_parent" 
  android:layout_height="0dip" 
  android:layout_weight="1" 
  android:layout_gravity="center" 
  android:background="#aabbcc"> 
 </FrameLayout> 
 
 <Button 
  android:layout_width="match_parent" 
  android:layout_height="wrap_content" 
  android:onClick="save" 
  android:text="保存签名" /> 
</LinearLayout> 

乍一看布局文件中并没有使用我们自定义的DrawView,不过不用着急我是使用了通过在FrameLayout中动态添加的方法把DrawView添加进来的,好了,那紧接着看看MainActivity中的代码实现吧:

public class MainActivity extends Activity { 
 
 private FrameLayout frameLayout; 
 private DrawView drawView; 
 private TextView title; 
 
 /** Called when the activity is first created. */ 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.main); 
 
  initWedgits(); 
 } 
 
 /** 
  * 初始化组件 
  */ 
 private void initWedgits() { 
  try { 
   frameLayout = (FrameLayout) findViewById(R.id.contents); 
   title = (TextView) findViewById(R.id.title); 
   title.setText(Html.fromHtml("<b>China中国<tt>中国</tt></b>China真伟大!")); 
 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
 
 @Override 
 public void onWindowFocusChanged(boolean hasFocus) { 
  drawView = new DrawView(MainActivity.this, frameLayout.getWidth(), frameLayout.getHeight()); 
  frameLayout.addView(drawView); 
 } 
 
 /** 
  * 保存图片 
  * 
  * @param view 
  */ 
 public void save(View view) { 
  try { 
   File file = new File(Environment.getExternalStorageDirectory() 
     .getAbsolutePath() + "/handle.png"); 
   if (file.exists()) { 
    file.delete(); 
   } 
   file.createNewFile(); 
   if (drawView.getBitmap().compress(CompressFormat.PNG, 100, new FileOutputStream(file))) { 
    Toast.makeText(getApplicationContext(), "图片保存成功", 1000).show(); 
   } 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
} 

在MainActivity中的代码没什么好解释的,相信你一看就懂,最主要的是在save方法中使用了Bitmap的compress()方法,就是把图片存储在文件中,当我们签名结束之后点击保存签名按钮,签名图片就保存在了本地文件中了,当然了如果你想上传到后台服务器也不难,就是使用个异步操作进行图片上传就行了...

说明:当你运行程序的时候,会看见China中国中国真伟大!的字样,其中China中国是加粗的效果,因为项目中有个需求让把汉字也加粗,上网上找了些方法,但是都是对英文和数字有效果对中文暂时没效果,我也是无意看源码中的注释,其中注释里边有加粗的文字说明,我就点击进去了,结果发现注释里的标签是<tt></tt>,当时脑子一转就想估计<tt>标签可以实现对汉字的加粗效果,呵呵,功夫不付有心人,把<tt>标签放到<b>里边已测试,果然有效果,呵呵,当时高兴坏了,现在再高兴一下,(*^__^*) 嘻嘻...

好了,现在我们运行程序来看一下效果图吧:

绘制签名:

当点击了保存按钮后,进入图库看看吧:

好了,数字签名的讲解到这里了,谢谢大家的阅读。

源码下载: Android UI实现数字签名效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持phpstudy。



相关阅读:
Java正则表达式入门学习
PHP return语句另类用法不止是在函数中
MySQL 启动报错:File ./mysql-bin.index not found (Errcode: 13)
Win8系统如何定时运行程序?Win8系统定时运行程序的方法
jQuery鼠标悬浮链接弹出跟随图片实例代码
require.js的用法详解
CSS实现五颜六色按钮组成的导航条效果代码
1亿条记录的MongoDB数据库随机查询性能测试
将HTML的左右尖括号等转义成实体形式的两种实现方式
百度地图API应用之获取用户的具体位置
C/C++实现字符串模糊匹配
Windows8下设置蓝牙配对的操作步骤
详解MySQL的用户密码过期功能
Android开发之Button事件实现与监听方法总结
快速导航
PHP MySQL HTML CSS JavaScript MSSQL AJAX .NET JSP Linux Mac ASP 服务器 SQL jQuery C# C++ java Android IOS oracle MongoDB SQLite wamp 交通频道 作文范文 太阳沟-江桥 信阳-源潭 许昌-沈阳北 新晃西-新化南 肇东-武威 依安-一面山 大兴-东光 广州北-深圳东 丰广-吉林 蓬安-金华 于都-商丘南 上饶-遂宁 阿城-兴凯 瓦房店-兴城 德阳-随州 昌平北-天镇 信丰-霸州 民族-孤山 余姚北-厦门北 塘沽-青县 开通-大乌苏 蚌埠南-嘉善南 留庄-捏掌 免渡河-绥阳 安康-瑞金 赵城-卓资东 湘潭-光山 一面坡-梨树镇 白山乡-兴安岭 福利屯-永胜 弋阳-霸州 昌图-寒葱沟 遵义-汝州 祁县-宣威 旌德-合肥南 宁东-海宁 吕梁-疏勒河 长武-咸阳 常州-巨野 琼海-海口 玉林-阳春 宁陵县-韶关东 昆山-济南 安顺-曲靖 开封北-湘潭北 齐齐哈尔-东边井 葫芦岛北-公主岭南 黄州-阳泉北 长春-祁阳 杨树岭-叶柏寿 封丘-长垣 缙云-宝鸡 安达-北京 大乌苏-铁岭 白涧-大灰厂 来宾-邵阳 新友谊-长春 梁山-来宾 光山-石家庄北 渭南北-曲阜东 枣阳-合肥 龙江-兴安岭 潍坊-嘉善 汉口-余姚北 古田北-桐乡 岳阳-普兰店 阜南-渭南 郴州-炎陵 德州-镇江 化州-靖州 浩良河-香兰 黄州-泰和 九江-玉山 威海北-荣成 富拉尔基-高台子 福州-天水 利川-株洲西 定边-滁州北 韶关东-万源 綦江-麻尾 朱熹的古诗一共有哪些
09年百里杜鹃的迎宾曲叫什么名字,用什么歌曲改编的也行??...
想知道在赤峰到北京的车票和北京到长沙的票都是提前多久卖啊
阜阳到乌兰察布需要多少时间,转不转车总钱数多少
西安到南台箱包市场怎么坐车南台的包怎么样跟白沟比,那个
从深圳到重庆开县的汽车客车票价要多少钱
广州火车列车站治安_广州火车列车站治安
济南到邯郸最早的一班车是几点?
在东莞这边坐什么列车火车回长沙最实惠早上到长沙的,我在东莞塘夏
从河南许昌到常州客车卧铺要票价多少钱
北京到婺源端午节旅游,跪求旅游路线,坐列车火车到九江后怎么安排
河南省禹州市去植物园的公交都有几路车啊?
谁可以帮我设计一条从 ( 吉安市到湖州 )的最佳路线?
明清时期的《黑山大战》
坐汽车济南至包头的车次和时间,请朋友帮忙,谢谢
上海列车火车站打的的地方在哪里?
叔叔阿姨从南昌到广州要做什么号的火车啊?
ems国际特快专递到日本的邮件问题
在哪能找到我被录取的名单
问一下 淄博博山窝疃社区2010年供暖价格 还有供暖时间
新疆的旅游景点有哪些?
在沈阳招聘客车修理工用什么方式能找到
D字头火车列车都是有哪些
青岛哈士奇到哪上证
上海到合肥的火车列车时刻表
广西河池职业学院的师资怎么样?
十堰市有到重庆巫溪的客车吗
从辽宁寄快递EMS到靖江要几天啊卖家说是20号发货的,今天26
请问在抚顺或者是营口,沈阳哪里有客车金融公司,我想贷款买车
砀山列车火车站可以预定10日后的列车火车票吗

Copyright © 2016 phpStudy |