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实现数字签名效果

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

(0)

相关推荐

  • Android自定义View设定到FrameLayout布局中实现多组件显示的方法 分享

    如果想在自定义的View上面显示Button 等View组件需要完成如下任务 1.在自定义View的类中覆盖父类的构造(注意是2个参数的) 复制代码 代码如下: public class MyView2 extends View{ public MyView2(Context context,AttributeSet att) {super(context,att); } public void onDraw(Canvas c) { // 这里绘制你要的内容 } } 2.定义布局文件 复制代码

  • Android自定义组件获取本地图片和相机拍照图片

    iOS中有封装好的选择图片后长按出现动画删除效果,效果如下 而Android找了很久都没有找到有这样效果的第三方组件,最后懒得找了还是自己实现这效果吧 选择图片后还可对图片进行剪裁 当然,代码中还有很多不完善的地方,我接下来会继续完善这个组件的 已经上传到开源社区,欢迎大家来Star啊~ Demo源码:传送门 设计中的碰到的一些问题和解决思路 1.如何让加号图片显示在GridView最后面 首先在调用GridAdapter构造方法时就加载加号图片 /** * 图片适配器 * @param con

  • Android自定义组件ListPopWindow

    先看一下效果: 效果就是这样,看一下实现,其实也没多难,就是想开源出来供小伙伴们使用,如有不合理地方,希望大家多多指正. 1.自定义PopWindow 首先我们分析一下,这样的效果肯定是一个PopWindow嵌套着listview,而上面的title.和下面的cancel是两个文本框,实现起来也比较简单. 然后我们在PopWindow中声明两个接口,用来回调cancel和item的点击事件 public interface OnPopItemClickListener{ void onPopIt

  • Android编程自定义组件实例详解

    本文实例讲述了Android编程自定义组件.分享给大家供大家参考,具体如下: 在Android中,所有的UI界面都是由View类和ViewGroup类及其子类组合而成.其中,View类是所有UI组件的基类,而ViewGroup类是容纳这些UI组件的容器. 其本身也是View类的子类. 在实际开发中,View类还不足以满足程序所有的需求.这时,便可以通过继承View类来开发自己的组件. 开发自定义组件的步骤: 1.创建一个继承android.view.View类的View类,并且重写构造方法. 2

  • Android中自定义Checkbox组件实例

    在Android中,Checkbox是一个很重要的UI组件,而且在Android中,它展现的形式越来越好看,这就说明有些系统,比如4.0以下,checkbox还是比较不好看,或者跟软件的风格不协调,就需要我们自定义这个组件. 自定义这个组件很简单,简单的增加修改xml文件即可. 准备工作 准备好两张图片,一个是选中的图片,另一个是未选中的图片.本文以checked.png和unchecked.png为例. 设置选择框 在drawable下新建文件custom_checkbox.xml 复制代码

  • Android实现Ant Design 自定义表单组件

    Ant Design 组件提供了Input,InputNumber,Radio,Select,uplod等表单组件,但实际开发中这是不能满足需求,同时我们希望可以继续使用Form提供的验证和提示等方法(使用起来确实很爽),这时需要自己动手封装一些表单,同时我们还要保持方法可以继续是使用. 组件的源码    https://github.com/haozhaohang/ant-design-expand-component 下面看一下如何自己封装表单组件,这是一个最基础的表单使用例子: impor

  • Android自定义加载loading view动画组件

    在github上找的一个有点酷炫的loading动画https://github.com/Fichardu/CircleProgress 我写写使用步骤 自定义view(CircleProgress )的代码 package com.hysmarthotel.view; import com.hysmarthotel.roomcontrol.R; import com.hysmarthotel.util.EaseInOutCubicInterpolator; import android.ani

  • Android 自定义组件成JAR包的实现方法

    Android 自定义组件成JAR包的实现方法,这里对自己实现的Android View 组件进行JAR 包的处理. 在项目开发过程中,我们难免会用到自己去制作自定义的VIEW控件,之后我们别的项目如果需要的话就直接将其复制到对应的项目中使用,虽说这么做是一个解决问题的方法,但毕竟不是很好. 原因是,当我们项目积累越来越多,会发现自定义的控件越来越多,而且这些自定义的控件都是可以重复利用的,这时我们可以想想,如果把这些自定义控件都封装成一个JAR包,然后用一个项目积累起来,之后我们以后开发项目只

  • android自定义组件实现方法

    本文实例讲述了android自定义组件实现方法.分享给大家供大家参考.具体如下: atts.xml: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="TopBar"> <attr name="titleText" format="string"/> <

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

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

  • Android UI设计系列之自定义ListView仿QQ空间阻尼下拉刷新和渐变菜单栏效果(8)

    好久没有写有关UI的博客了,刚刚翻了一下之前的博客,最近一篇有关UI的博客:Android UI设计系列之自定义Dialog实现各种风格的对话框效果(7) ,实现各种风格效果的对话框,在那篇博客写完后由于公司封闭开发封网以及其它原因致使博客中断至今,中断这么久很是惭愧,后续我会尽量把该写的都补充出来.近来项目有个需求,要做个和QQ空间类似的菜单栏透明度渐变和下拉刷新带有阻尼回弹的效果.于是花点时间动手试了试,基本上达到了QQ空间的效果,截图如下: 通过观察QQ空间的运行效果,发现当往上滚动时菜单

  • Android UI设计系列之自定义Dialog实现各种风格的对话框效果(7)

    虽然Android给我们提供了众多组件,但是使用起来都不是很方便,我们开发的APK都有自己的风格,如果使用了系统自带的组件,总是觉得和应用的主题不着边际并且看起来也不顺心,那我们就需要自定义了,为了方便大家对自定义组件的学习,我接下来准备了几遍有关自定义的Dialog的文章,希望对大家有帮助. 在开发APK中最常见的估计就数弹出对话框了,这种对话框按照按钮数量来分大致是三种:一个按钮,两个按钮,三个按钮.现在要讲的就是按照按钮数量分为以上三类吧(当然了可以有更多的按钮,只要你愿意). 自定义Di

  • Android UI设计系列之自定义ViewGroup打造通用的关闭键盘小控件ImeObserverLayout(9)

    转载请注明出处:http://blog.csdn.net/llew2011/article/details/51598682 我们平时开发中总会遇见一些奇葩的需求,为了实现这些需求我们往往绞尽脑汁有时候还茶不思饭不香的,有点夸张了(*^__^*)--我印象最深的一个需求是在一段文字中对部分词语进行加粗显示.当时费了不少劲,不过还好,这个问题最终解决了,有兴趣的童靴可以看一下:Android UI设计之<六>使用HTML标签,实现在TextView中对部分文字进行加粗显示. 之前产品那边提了这样

  • Android UI设计系列之自定义TextView属性实现带下划线的文本框(4)

    在Android开发过程中,如果Android系统自带的属性不能满足我们日常开发的需求,那么就需要我们给系统控件添加额外的属性了.假如有个需求是实现带下划线的文本显示(下划线),如果不使用自定义属性的话实现起来也不太难(起码我认为的实现方式是有许多种的),今天就讲解一下如何使用自定义属性来实现上述带下划线的文本框吧.还好Android中自定义属性不是很复杂,也可以归纳为三步走吧. 老规矩,还是先贴出工程目录吧: 一.添加属性文件 在values文件夹中新建attrs.xml文件,在文件中新建属性

  • Android UI设计系列之自定义SwitchButton开关实现类似IOS中UISwitch的动画效果(2)

    做IOS开发的都知道,IOS提供了一个具有动态开关效果的UISwitch组件,这个组件很好用效果相对来说也很绚丽,当我们去点击开关的时候有动画效果,但遗憾的是Android上并没有给我们提供类似的组件(听说在Android4.0的版本上提供了具有动态效果的开关组件,不过我还没有去看文档),如果我们想实现类似的效果那该怎么办了呢?看来又得去自定义了. 公司的产品最近一直在做升级,主要做的就是把界面做的更绚丽更美观给用户更好的体验(唉,顾客是上帝......),其中的设置功能中就有开关按钮,原来的开

  • Android UI设计系列之自定义EditText实现带清除功能的输入框(3)

    最近公司的产品在陆续做升级,上级领导给的任务是优化代码结构以及项目架构,力争把项目写的精巧简练,于是我们满工程找冗余... 我们都知道每一个项目基本上都是有登陆页的,在登陆页中肯定是少不了输入框了,当我们在输入框中输入数据后如果输入的内容不正确或者是错误的或者是想重新输入,如果嗯键盘上的删除键就得一个一个的去删除,这时候我们或许就想要是能有一个标记当点击了这个标记能把我们刚刚输入的内容清空就好了.这样可以极大的提升用户体验,就拿QQ的登陆来说吧,效果如下: 当点击密码框右侧的小×图标时输入的内容

  • Android UI设计系列之ImageView实现ProgressBar旋转效果(1)

    提起ProgressBar,想必大家都比较熟悉,使用起来也是比较方便,直接在XML文件中引用,然后添加属性,运行就OK了,虽然使用ProgressBar很方便但是在我们开发的每一个应用基本上都有自己的主体风格,如果使用了系统自带的效果图,给人的感觉是和总体风格太不搭配了,看上去很是别扭,我们自己开发也觉得不爽,于是就想着自定义一下效果,其实自定义ProgressBar的效果也不难,大概可分为三步走吧: 一.在anim文件夹下使用animation-list定义动画集 <?xml version=

  • Android UI设计系列之HTML标签实现TextView设置中文字体加粗效果(6)

    搞软件开发的都知道项目中各种需求都有,而有时候各种奇葩的需求真是让人大跌眼镜,为了实现这些奇葩的需求我们往往苦逼的废寝忘食,我现在的项目中就有一个应该算得上奇葩的需求吧,需求是这样的:在一段文字中实现对部分文字加粗 这个看上去也不难并且有点小儿科,因为TextView中有个属性是Android:textStyle,它其中一个值是bold,也就是说是对将要显示的文字进行加粗,于是我就在TextView控件中添加了此属性,代码如下: <TextView android:layout_width=&quo

  • Android UI设计与开发之实现应用程序只启动一次引导界面

    这篇文章算是对整个引导界面开发专题的一个终结了吧,个人觉得大部分的引导界面基本上都是千篇一律的,只要熟练掌握了一个,基本上也就没什么好说的了,要是在今后的开发中遇到了更好玩,更有趣的引导界面,博主也会在这里及时的跟大家分享,今天的内容主要是教大家的应用程序只有在第一次启动的时候显示引导界面,以后在启动程序的时候就不再显示了. 其实要想实现这样的效果,只要使用SharedPreferences类,就会让程序变的非常简单,下面来详细介绍一下这个类的使用方法 一.SharedPreferences的详

随机推荐