欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义UI手势密码改进版源码下载

程序员文章站 2024-03-02 17:44:16
在之前文章的铺垫下,再为大家分享一篇:android手势密码,附源码下载,不要错过。 源码下载:http://xiazai.jb51.net/201610/yuanm...

在之前文章的铺垫下,再为大家分享一篇:android手势密码,附源码下载,不要错过。

Android自定义UI手势密码改进版源码下载

源码下载:http://xiazai.jb51.net/201610/yuanma/androidlock(jb51.net).rar

先看第一张图片的布局文件

activity_main.xml

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:orientation="vertical" 
 android:gravity="center_horizontal" > 
 
 <textview 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:layout_margintop="40dip" 
 android:textsize="24sp" 
 android:text="手势密码" /> 
 
 <button 
 android:id="@+id/btn_set_lockpattern" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:layout_margintop="50dip" 
 android:text="设置手势密码" /> 
 
 <button 
 android:id="@+id/btn_verify_lockpattern" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:layout_margintop="10dip" 
 android:text="校验手势密码" /> 
 
 <textview 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:layout_margintop="10dip" 
 android:text="密码图案是大2"/> 
 
</linearlayout> 

再看上面布局的java代码
mainactivity

package com.wujay.fund; 
 
import android.app.activity; 
import android.content.intent; 
import android.os.bundle; 
import android.view.view; 
import android.view.view.onclicklistener; 
import android.widget.button; 
 
public class mainactivity extends activity implements onclicklistener { 
 private button mbtnsetlock; 
 private button mbtnverifylock; 
 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
 super.oncreate(savedinstancestate); 
 setcontentview(r.layout.activity_main); 
 setupview(); 
 setuplistener(); 
 } 
 
 private void setupview() { 
 mbtnsetlock = (button) findviewbyid(r.id.btn_set_lockpattern); 
 mbtnverifylock = (button) findviewbyid(r.id.btn_verify_lockpattern); 
 } 
 
 private void setuplistener() { 
 mbtnsetlock.setonclicklistener(this); 
 mbtnverifylock.setonclicklistener(this); 
 } 
 
 @override 
 public void onclick(view v) { 
 switch (v.getid()) { 
 case r.id.btn_set_lockpattern: 
  startsetlockpattern(); 
  break; 
 case r.id.btn_verify_lockpattern: 
  startverifylockpattern(); 
  break; 
 default: 
  break; 
 } 
 } 
 
 private void startsetlockpattern() { 
 intent intent = new intent(mainactivity.this, gestureeditactivity.class); 
 startactivity(intent); 
 } 
 
 private void startverifylockpattern() { 
 intent intent = new intent(mainactivity.this, gestureverifyactivity.class); 
 startactivity(intent); 
 } 
} 

另外看下工具类和bean类
apputil

package com.wujay.fund.common; 
 
import android.content.context; 
import android.view.windowmanager; 
 
public class apputil { 
 public static int[] getscreendispaly(context context) { 
 windowmanager windowmanager = (windowmanager) context 
  .getsystemservice(context.window_service); 
 int width = windowmanager.getdefaultdisplay().getwidth();// 手机屏幕的宽度 
 int height = windowmanager.getdefaultdisplay().getheight();// 手机屏幕的高度 
 int result[] = { width, height }; 
 return result; 
 } 
} 

再看9宫格的单位bean类
gesturepoint

package com.wujay.fund.entity; 
 
 
import com.wujay.fund.r; 
import com.wujay.fund.common.constants; 
 
import android.widget.imageview; 
 
public class gesturepoint { 
 /** 
 * 状态值 
 */ 
 private int pointstate; 
 
 /** 代表这个point对象代表的数字,从1开始(直接感觉从1开始)*/ 
 private int num; 
 private int leftx; 
 private int rightx; 
 private int topy; 
 private int bottomy; 
 private imageview image; 
 
 private int centerx; 
 private int centery; 
 public gesturepoint(int leftx, int rightx, int topy, int bottomy, 
  imageview image, int num) { 
 super(); 
 this.leftx = leftx; 
 this.rightx = rightx; 
 this.topy = topy; 
 this.bottomy = bottomy; 
 this.image = image; 
 
 this.centerx = (leftx + rightx) / 2; 
 this.centery = (topy + bottomy) / 2; 
 
 this.num = num; 
 } 
 
 public int getleftx() { 
 return leftx; 
 } 
 
 public void setleftx(int leftx) { 
 this.leftx = leftx; 
 } 
 
 public int getrightx() { 
 return rightx; 
 } 
 
 public void setrightx(int rightx) { 
 this.rightx = rightx; 
 } 
 
 public int gettopy() { 
 return topy; 
 } 
 
 public void settopy(int topy) { 
 this.topy = topy; 
 } 
 
 public int getbottomy() { 
 return bottomy; 
 } 
 
 public void setbottomy(int bottomy) { 
 this.bottomy = bottomy; 
 } 
 
 public imageview getimage() { 
 return image; 
 } 
 
 public void setimage(imageview image) { 
 this.image = image; 
 } 
 
 public int getcenterx() { 
 return centerx; 
 } 
 
 public void setcenterx(int centerx) { 
 this.centerx = centerx; 
 } 
 
 public int getcentery() { 
 return centery; 
 } 
 
 public void setcentery(int centery) { 
 this.centery = centery; 
 } 
 
 public int getpointstate() { 
 return pointstate; 
 } 
 
 public void setpointstate(int state) { 
 pointstate = state; 
 switch (state) { 
 case constants.point_state_normal: 
  this.image.setbackgroundresource(r.drawable.gesture_node_normal); 
  break; 
 case constants.point_state_selected: 
  this.image.setbackgroundresource(r.drawable.gesture_node_pressed); 
  break; 
 case constants.point_state_wrong: 
  this.image.setbackgroundresource(r.drawable.gesture_node_wrong); 
  break; 
 default: 
  break; 
 } 
 } 
 
 public int getnum() { 
 return num; 
 } 
 
 public void setnum(int num) { 
 this.num = num; 
 } 
 
 @override 
 public int hashcode() { 
 final int prime = 31; 
 int result = 1; 
 result = prime * result + bottomy; 
 result = prime * result + ((image == null) ? 0 : image.hashcode()); 
 result = prime * result + leftx; 
 result = prime * result + rightx; 
 result = prime * result + topy; 
 return result; 
 } 
 
 @override 
 public boolean equals(object obj) { 
 if (this == obj) 
  return true; 
 if (obj == null) 
  return false; 
 if (getclass() != obj.getclass()) 
  return false; 
 gesturepoint other = (gesturepoint) obj; 
 if (bottomy != other.bottomy) 
  return false; 
 if (image == null) { 
  if (other.image != null) 
  return false; 
 } else if (!image.equals(other.image)) 
  return false; 
 if (leftx != other.leftx) 
  return false; 
 if (rightx != other.rightx) 
  return false; 
 if (topy != other.topy) 
  return false; 
 return true; 
 } 
 
 @override 
 public string tostring() { 
 return "point [leftx=" + leftx + ", rightx=" + rightx + ", topy=" 
  + topy + ", bottomy=" + bottomy + "]"; 
 } 
} 

再看每个点位的3种状态
constants

package com.wujay.fund.common; 

public class constants { 
public static final int point_state_normal = 0; // 正常状态 
public static final int point_state_selected = 1; // 按下状态 
public static final int point_state_wrong = 2; // 错误状态 

} 


再看来绘制密码的界面
activity_gesture_edit.xml

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:background="#48423d" > 
 
 <relativelayout 
 android:id="@+id/top_layout" 
 android:layout_width="match_parent" 
 android:layout_height="46dip" 
 android:background="#000000" 
 android:paddingleft="20dip" 
 android:paddingright="20dip" 
 android:layout_alignparenttop="true" > 
 
 <textview 
  android:id="@+id/text_title" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_centerinparent="true" 
  android:gravity="center" 
  android:text="@string/setup_gesture_code" 
  android:textsize="20sp" 
  android:textcolor="#ffffff" /> 
 </relativelayout> 
 
 <linearlayout 
 android:id="@+id/gesture_tip_layout" 
 android:layout_width="fill_parent" 
 android:layout_height="wrap_content" 
 android:layout_below="@id/top_layout" 
 android:gravity="center" 
 android:orientation="vertical" > 
 
 
 <textview 
  android:id="@+id/text_tip" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:gravity="center_horizontal" 
  android:text="@string/set_gesture_pattern" 
  android:textcolor="#f98f12" 
  android:layout_margintop="10dip" /> 
 </linearlayout> 
 
 <framelayout 
 android:id="@+id/gesture_container" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:layout_below="@id/gesture_tip_layout" 
 android:layout_gravity="center_horizontal" 
 android:layout_margintop="20dip" > 
 </framelayout> 
 
 <textview 
 android:id="@+id/text_reset" 
 android:layout_width="fill_parent" 
 android:layout_height="wrap_content" 
 android:gravity="center_horizontal" 
 android:layout_below="@id/gesture_container" 
 android:layout_margintop="20dip" 
 android:text="@string/set_gesture_pattern_reason" 
 android:textcolor="#816e6a" /> 
 
</relativelayout> 

再看来绘制密码的类
gestureeditactivity

package com.wujay.fund; 
 
import com.wujay.fund.r; 
import android.app.activity; 
import android.os.bundle; 
import android.text.html; 
import android.text.textutils; 
import android.view.view; 
import android.view.view.onclicklistener; 
import android.view.animation.animation; 
import android.view.animation.animationutils; 
import android.widget.framelayout; 
import android.widget.textview; 
import android.widget.toast; 
import com.wujay.fund.widget.gesturecontentview; 
import com.wujay.fund.widget.gesturedrawline.gesturecallback; 
 
/** 
 * 手势密码设置界面 
 */ 
public class gestureeditactivity extends activity implements onclicklistener { 
 // 2次绘制手势密码不正确的提示语 
 private textview mtexttip; 
 // 手势密码绘制区域 
 private framelayout mgesturecontainer; 
 private gesturecontentview mgesturecontentview; 
 // 重新设置手势密码 
 private textview mtextreset; 
 // 是否是第一次绘制密码锁 
 private boolean misfirstinput = true; 
 // 初次绘制完毕密码锁,生成的密码 
 private string mfirstpassword = null; 
 
 @override 
 public void oncreate(bundle savedinstancestate) { 
 super.oncreate(savedinstancestate); 
 setcontentview(r.layout.activity_gesture_edit); 
 setupviews(); 
 setuplisteners(); 
 } 
 
 /** 
 * 判断初次绘制完毕生成的密码判断 判断是不是为空 判断密码数量是不是小于4 
 */ 
 private boolean isinputpassvalidate(string inputpassword) { 
 if (textutils.isempty(inputpassword) || inputpassword.length() < 4) { 
  return false; 
 } 
 return true; 
 } 
 
 private void setupviews() { 
 // 重新设置手势密码 
 mtextreset = (textview) findviewbyid(r.id.text_reset); 
 // 默认不可点击 
 mtextreset.setclickable(false); 
 // 2次绘制手势密码不正确的提示语 
 mtexttip = (textview) findviewbyid(r.id.text_tip); 
 // 手势密码绘制区域 
 mgesturecontainer = (framelayout) findviewbyid(r.id.gesture_container); 
 /** 
  * 初始化一个显示各个点的viewgroup gesturecontentview(context context, boolean 
  * isverify, string password, gesturecallback callback) 
  */ 
 mgesturecontentview = new gesturecontentview(this, false, "", 
  new gesturecallback() { 
   @override 
   public void ongesturecodeinput(string inputcode) { 
   // 验证输入的图案密码--如果密码为null。或者密码个数少于4个 
   if (!isinputpassvalidate(inputcode)) { 
    mtexttip.settext(html 
     .fromhtml("<font color='#c70c1e'>最少链接4个点, 请重新输入</font>")); 
    // 立刻清楚画的线段 
    mgesturecontentview.cleardrawlinestate(0l); 
    return; 
   } 
   if (misfirstinput) { 
    // 第一次输入密码--保存第一次输入的密码,在进行跟第二次判断 
    mfirstpassword = inputcode; 
    // 第一次输入完毕后,立刻清楚画的线段 
    mgesturecontentview.cleardrawlinestate(0l); 
    // 设置可以重新设置密码锁的状态按钮 
    mtextreset.setclickable(true); 
    mtextreset 
     .settext(getstring(r.string.reset_gesture_code)); 
   } else { 
    if (inputcode.equals(mfirstpassword)) { 
    toast.maketext(gestureeditactivity.this, 
     "设置成功", toast.length_short).show(); 
    mgesturecontentview.cleardrawlinestate(0l); 
    gestureeditactivity.this.finish(); 
    } else { 
    mtexttip.settext(html 
     .fromhtml("<font color='#c70c1e'>与上一次绘制不一致,请重新绘制</font>")); 
    // 左右移动动画 
    animation shakeanimation = animationutils 
     .loadanimation( 
      gestureeditactivity.this, 
      r.anim.shake); 
    mtexttip.startanimation(shakeanimation); 
    // 保持绘制的线,1.5秒后清除 
    mgesturecontentview.cleardrawlinestate(1300l); 
    } 
   } 
   misfirstinput = false; 
   } 
 
   @override 
   public void checkedsuccess() { 
 
   } 
 
   @override 
   public void checkedfail() { 
 
   } 
  }); 
 // 设置手势解锁显示到哪个布局里面 
 mgesturecontentview.setparentview(mgesturecontainer); 
 } 
 
 /*****************************************************/ 
 private void setuplisteners() { 
 mtextreset.setonclicklistener(this); 
 } 
 
 @override 
 public void onclick(view v) { 
 switch (v.getid()) { 
 case r.id.text_reset: 
  misfirstinput = true; 
  mtexttip.settext(getstring(r.string.set_gesture_pattern)); 
  break; 
 default: 
  break; 
 } 
 } 
 
} 

gesturecontentview

package com.wujay.fund.widget; 
 
import java.util.arraylist; 
import java.util.list; 
import android.content.context; 
import android.view.view; 
import android.view.viewgroup; 
import android.widget.imageview; 
import com.wujay.fund.r; 
import com.wujay.fund.common.apputil; 
import com.wujay.fund.entity.gesturepoint; 
import com.wujay.fund.widget.gesturedrawline.gesturecallback; 
 
/** 
 * 手势密码容器类 
 */ 
public class gesturecontentview extends viewgroup { 
 private gesturedrawline gesturedrawline; 
 
 /************************************************************************ 
 * 包含9个imageview的容器,初始化 
 * 
 * @param context 
 * @param isverify 
 *  是否为校验手势密码 
 * @param password 
 *  用户传入密码 
 * @param callback 
 *  手势绘制完毕的回调 
 */ 
 private int[] screendispaly; 
 // 将屏幕宽度分成3份 
 private int blockwidth; 
 // 9个点位的集合 
 private list<gesturepoint> list; 
 // 环境 
 private context context; 
 // 是否需要校验密码 
 private boolean isverify; 
 
 public gesturecontentview(context context, boolean isverify, 
  string password, gesturecallback callback) { 
 super(context); 
 // 获取屏幕宽度 
 screendispaly = apputil.getscreendispaly(context); 
 // 获取屏幕宽度的1/3 
 blockwidth = screendispaly[0] / 3; 
 this.list = new arraylist<gesturepoint>(); 
 this.context = context; 
 this.isverify = isverify; 
 // 添加9个图标 
 addchild(); 
 // 初始化一个可以画线的view 
 gesturedrawline = new gesturedrawline(context, list, isverify, 
  password, callback); 
 } 
 
 /** 
 * 添加9个圆点的图标 
 */ 
 // 用来计算2个圆心之间的一半距离大小 
 private int basenum = 6; 
 
 private void addchild() { 
 for (int i = 0; i < 9; i++) { 
  imageview image = new imageview(context); 
  image.setbackgroundresource(r.drawable.gesture_node_normal); 
  this.addview(image); 
  invalidate(); 
  // 第几行---012 0 ,345 1, 678 2-- 
  int row = i / 3; 
  // 第几列---012 012 , 345 012 , 678 012 
  int col = i % 3; 
  // 定义点的每个属性 
  int leftx = col * blockwidth + blockwidth / basenum; 
  int topy = row * blockwidth + blockwidth / basenum; 
  int rightx = col * blockwidth + blockwidth - blockwidth / basenum; 
  int bottomy = row * blockwidth + blockwidth - blockwidth / basenum; 
  // 构建圆点对象 
  gesturepoint p = new gesturepoint(leftx, rightx, topy, bottomy, 
   image, i + 1); 
  // 添加9个圆点图标 
  this.list.add(p); 
 } 
 } 
 
 /** 
 * 设置手势解锁显示到哪个布局里面 
 */ 
 
 public void setparentview(viewgroup parent) { 
 // 得到屏幕的宽度 
 int width = screendispaly[0]; 
 // 设置手势锁的宽度高度--以屏幕的宽为基准 
 layoutparams layoutparams = new layoutparams(width, width); 
 // 设置手势锁的宽度高度--以屏幕的宽为基准 
 this.setlayoutparams(layoutparams); 
 // 将线路绘制也做同样的操作 
 gesturedrawline.setlayoutparams(layoutparams); 
 parent.addview(gesturedrawline); 
 parent.addview(this); 
 } 
 
 /************************************** 绘制圆点位操作 ****************************************/ 
 @override 
 protected void onlayout(boolean changed, int l, int t, int r, int b) { 
 // 循环获取里面的每一个圆点位 
 for (int i = 0; i < getchildcount(); i++) { 
  // 第几行 
  int row = i / 3; 
  // 第几列 
  int col = i % 3; 
  // 获取对应的圆点位 
  view v = getchildat(i); 
  // 进行圆点位的绘制操作 
  v.layout(col * blockwidth + blockwidth / basenum, row * blockwidth 
   + blockwidth / basenum, col * blockwidth + blockwidth 
   - blockwidth / basenum, row * blockwidth + blockwidth 
   - blockwidth / basenum); 
 } 
 } 
 
 @override 
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { 
 super.onmeasure(widthmeasurespec, heightmeasurespec); 
 // 遍历设置每个子view的大小 
 for (int i = 0; i < getchildcount(); i++) { 
  view v = getchildat(i); 
  v.measure(widthmeasurespec, heightmeasurespec); 
 } 
 } 
 
 /** 
 * 对外暴露一个方法---用于清楚密码锁上的线段 保留路径delaytime时间长 
 * 
 * @param delaytime 
 */ 
 public void cleardrawlinestate(long delaytime) { 
 gesturedrawline.cleardrawlinestate(delaytime); 
 } 
 
} 

gesturedrawline

package com.wujay.fund.widget; 
 
import java.util.arraylist; 
import java.util.hashmap; 
import java.util.list; 
import java.util.map; 
import com.wujay.fund.common.apputil; 
import com.wujay.fund.common.constants; 
import com.wujay.fund.entity.gesturepoint; 
import android.content.context; 
import android.graphics.bitmap; 
import android.graphics.canvas; 
import android.graphics.color; 
import android.graphics.paint; 
import android.graphics.paint.style; 
import android.graphics.porterduff; 
import android.os.handler; 
import android.util.log; 
import android.util.pair; 
import android.view.motionevent; 
import android.view.view; 
import android.widget.toast; 
 
/** 
 * 手势密码路径绘制 
 * 
 */ 
public class gesturedrawline extends view { 
 private int mov_x;// 声明起点坐标 
 private int mov_y; 
 
 private map<string, gesturepoint> autocheckpointmap;// 自动选中的情况点 
 private boolean isdrawenable = true; // 是否允许绘制 
 
 /********************************************************************** 
 * 构造函数 
 */ 
 private int[] screendispaly; 
 private paint paint;// 声明画笔 
 private canvas canvas;// 画布 
 private bitmap bitmap;// 位图 
 private list<gesturepoint> list;// 装有各个view坐标的集合 
 private list<pair<gesturepoint, gesturepoint>> linelist;// 记录画过的线 
 private stringbuilder passwordsb; 
 private boolean isverify; 
 private string password; 
 private gesturecallback callback; 
 
 public gesturedrawline(context context, list<gesturepoint> list, 
  boolean isverify, string password, gesturecallback callback) { 
 super(context); 
 screendispaly = apputil.getscreendispaly(context); 
 paint = new paint(paint.dither_flag);// 创建一个画笔 
 bitmap = bitmap.createbitmap(screendispaly[0], screendispaly[0], 
  bitmap.config.argb_8888); // 设置位图的宽高 
 canvas = new canvas(); 
 canvas.setbitmap(bitmap);// 用声明的画笔在位图上画点位 
 
 paint.setstyle(style.stroke);// 设置非填充 
 paint.setstrokewidth(10);// 笔宽5像素 
 paint.setcolor(color.rgb(245, 142, 33));// 设置默认连线颜色 
 paint.setantialias(true);// 不显示锯齿 
 
 this.list = list; 
 this.linelist = new arraylist<pair<gesturepoint, gesturepoint>>(); 
 
 initautocheckpointmap(); 
 this.callback = callback; 
 
 // 初始化密码缓存 
 this.isverify = isverify; 
 this.passwordsb = new stringbuilder(); 
 this.password = password; 
 } 
 
 private void initautocheckpointmap() { 
 autocheckpointmap = new hashmap<string, gesturepoint>(); 
 autocheckpointmap.put("1,3", getgesturepointbynum(2)); 
 autocheckpointmap.put("1,7", getgesturepointbynum(4)); 
 autocheckpointmap.put("1,9", getgesturepointbynum(5)); 
 autocheckpointmap.put("2,8", getgesturepointbynum(5)); 
 autocheckpointmap.put("3,7", getgesturepointbynum(5)); 
 autocheckpointmap.put("3,9", getgesturepointbynum(6)); 
 autocheckpointmap.put("4,6", getgesturepointbynum(5)); 
 autocheckpointmap.put("7,9", getgesturepointbynum(8)); 
 } 
 
 private gesturepoint getgesturepointbynum(int num) { 
 for (gesturepoint point : list) { 
  if (point.getnum() == num) { 
  return point; 
  } 
 } 
 return null; 
 } 
 
 /********************************************************** 
 * 画位图 
 */ 
 @override 
 protected void ondraw(canvas canvas) { 
 canvas.drawbitmap(bitmap, 0, 0, paint); 
 
 } 
 
 /** 
 * 通过点的位置去集合里面查找这个点是包含在哪个point里面的 
 * 
 * @return 如果没有找到,则返回null,代表用户当前移动的地方属于点与点之间 
 */ 
 private gesturepoint getpointat(int x, int y) { 
 
 for (gesturepoint point : list) { 
  // 先判断x 
  int leftx = point.getleftx(); 
  int rightx = point.getrightx(); 
  if (!(x >= leftx && x < rightx)) { 
  // 如果为假,则跳到下一个对比 
  continue; 
  } 
 
  int topy = point.gettopy(); 
  int bottomy = point.getbottomy(); 
  if (!(y >= topy && y < bottomy)) { 
  // 如果为假,则跳到下一个对比 
  continue; 
  } 
 
  // 如果执行到这,那么说明当前点击的点的位置在遍历到点的位置这个地方 
  return point; 
 } 
 
 return null; 
 } 
 
 /** 
 * 清掉屏幕上所有的线,然后画出集合里面的线 
 */ 
 private void clearscreenanddrawlist() { 
 canvas.drawcolor(color.transparent, porterduff.mode.clear); 
 for (pair<gesturepoint, gesturepoint> pair : linelist) { 
  // drawline(float startx, float starty, float stopx, float stopy, 
  // paint paint) 
  canvas.drawline(pair.first.getcenterx(), pair.first.getcentery(), 
   pair.second.getcenterx(), pair.second.getcentery(), paint);// 画线 
 } 
 } 
 
 /** 
 * 判断是否中间点需要选中 
 * 
 * @param pointstart 
 * @param pointend 
 * @return 
 */ 
 private gesturepoint getbetweencheckpoint(gesturepoint pointstart, 
  gesturepoint pointend) { 
 int startnum = pointstart.getnum(); 
 int endnum = pointend.getnum(); 
 string key = null; 
 if (startnum < endnum) { 
  key = startnum + "," + endnum; 
 } else { 
  key = endnum + "," + startnum; 
 } 
 return autocheckpointmap.get(key); 
 } 
 
 /** 
 * 触摸事件 
 */ 
 private gesturepoint currentpoint; 
 
 @override 
 public boolean ontouchevent(motionevent event) { 
 if (isdrawenable == false) { 
  // 如果圆点图片呈现红色的底片--也就是二次绘制错误,在没有清楚绘制的线段的情况下,不再允许绘制线条 
  return true; 
 } 
 paint.setcolor(color.rgb(245, 142, 33));// 设置默认连线颜色 
 switch (event.getaction()) { 
 case motionevent.action_down: 
  // 鼠标按下后,获取手指点位的xy坐标 
  mov_x = (int) event.getx(); 
  mov_y = (int) event.gety(); 
  // 判断当前点击的位置是处于哪个点之内 
  currentpoint = getpointat(mov_x, mov_y); 
  if (currentpoint != null) { 
  currentpoint.setpointstate(constants.point_state_selected); 
  passwordsb.append(currentpoint.getnum()); 
  } 
  invalidate(); 
  break; 
 case motionevent.action_move: 
  // 清掉屏幕上所有的线,然后画出集合里面的线--不然的话不是一条线 
  clearscreenanddrawlist(); 
 
  // 得到当前移动位置是处于哪个点内 
  gesturepoint pointat = getpointat((int) event.getx(), 
   (int) event.gety()); 
  // 代表当前用户手指处于点与点之前 
  if (currentpoint == null && pointat == null) { 
  return true; 
  } else {// 代表用户的手指从点与点之间移动到了点上 
  if (currentpoint == null) {// 先判断当前的point是不是为null 
   // 如果为空,那么把手指移动到的点赋值给currentpoint 
   currentpoint = pointat; 
   // 把currentpoint这个点设置选中为true; 
   currentpoint.setpointstate(constants.point_state_selected); 
   passwordsb.append(currentpoint.getnum()); 
  } 
  } 
  if (pointat == null || currentpoint.equals(pointat)) { 
  // 点击移动区域不在圆的区域,或者当前点击的点与当前移动到的点的位置相同 
  // 那么以当前的点中心为起点,以手指移动位置为终点画线 
  canvas.drawline(currentpoint.getcenterx(), 
   currentpoint.getcentery(), event.getx(), event.gety(), 
   paint);// 画线 
  } else { 
  // 如果当前点击的点与当前移动到的点的位置不同 
  // 那么以前前点的中心为起点,以手移动到的点的位置画线 
  canvas.drawline(currentpoint.getcenterx(), 
   currentpoint.getcentery(), pointat.getcenterx(), 
   pointat.getcentery(), paint);// 画线 
  pointat.setpointstate(constants.point_state_selected); 
 
  // 判断是否中间点需要选中 
  gesturepoint betweenpoint = getbetweencheckpoint(currentpoint, 
   pointat); 
  if (betweenpoint != null 
   && constants.point_state_selected != betweenpoint 
    .getpointstate()) { 
   // 存在中间点并且没有被选中 
   pair<gesturepoint, gesturepoint> pair1 = new pair<gesturepoint, gesturepoint>( 
    currentpoint, betweenpoint); 
   linelist.add(pair1); 
   passwordsb.append(betweenpoint.getnum()); 
   pair<gesturepoint, gesturepoint> pair2 = new pair<gesturepoint, gesturepoint>( 
    betweenpoint, pointat); 
   linelist.add(pair2); 
   passwordsb.append(pointat.getnum()); 
   // 设置中间点选中 
   betweenpoint.setpointstate(constants.point_state_selected); 
   // 赋值当前的point; 
   currentpoint = pointat; 
  } else { 
   pair<gesturepoint, gesturepoint> pair = new pair<gesturepoint, gesturepoint>( 
    currentpoint, pointat); 
   linelist.add(pair); 
   passwordsb.append(pointat.getnum()); 
   // 赋值当前的point; 
   currentpoint = pointat; 
  } 
  } 
  invalidate(); 
  break; 
 case motionevent.action_up:// 当手指抬起的时候 
  if (isverify) { 
  // 手势密码校验 
  // 清掉屏幕上所有的线,只画上集合里面保存的线 
  if (password.equals(passwordsb.tostring())) { 
   // 代表用户绘制的密码手势与传入的密码相同 
   callback.checkedsuccess(); 
  } else { 
   // 用户绘制的密码与传入的密码不同。 
   callback.checkedfail(); 
  } 
  } else { 
  callback.ongesturecodeinput(passwordsb.tostring()); 
  } 
  break; 
 default: 
  break; 
 } 
 return true; 
 } 
 
 /************************************ 
 * 校验错误/两次绘制不一致提示 
 */ 
 private void drawerrorpathtip() { 
 canvas.drawcolor(color.transparent, porterduff.mode.clear); 
 paint.setcolor(color.rgb(154, 7, 21));// 设置默认线路颜色 
 for (pair<gesturepoint, gesturepoint> pair : linelist) { 
  pair.first.setpointstate(constants.point_state_wrong); 
  pair.second.setpointstate(constants.point_state_wrong); 
  canvas.drawline(pair.first.getcenterx(), pair.first.getcentery(), 
   pair.second.getcenterx(), pair.second.getcentery(), paint);// 画线 
 } 
 invalidate(); 
 } 
 
 /** 
 * 指定时间去清除绘制的状态 
 * 
 * @param delaytime 
 *  延迟执行时间 
 */ 
 public void cleardrawlinestate(long delaytime) { 
 if (delaytime > 0) { 
  // 绘制红色提示路线 
  isdrawenable = false; 
  drawerrorpathtip(); 
 } 
 new handler().postdelayed(new clearstaterunnable(), delaytime); 
 } 
 
 /************************************************* 
 * 清除绘制状态的线程 
 */ 
 final class clearstaterunnable implements runnable { 
 public void run() { 
  // 重置passwordsb 
  passwordsb = new stringbuilder(); 
  // 清空保存点的集合 
  linelist.clear(); 
  // 重新绘制界面 
  clearscreenanddrawlist(); 
  for (gesturepoint p : list) { 
  p.setpointstate(constants.point_state_normal); 
  } 
  invalidate(); 
  isdrawenable = true; 
 } 
 } 
 
 public interface gesturecallback { 
 
 /** 
  * 用户设置/输入了手势密码 
  */ 
 public abstract void ongesturecodeinput(string inputcode); 
 
 /** 
  * 代表用户绘制的密码与传入的密码相同 
  */ 
 public abstract void checkedsuccess(); 
 
 /** 
  * 代表用户绘制的密码与传入的密码不相同 
  */ 
 public abstract void checkedfail(); 
 } 
 
} 

接下来看验证密码锁的布局
activity_gesture_verify.xml

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:background="#48443c" > 
 
 
 <linearlayout 
 android:id="@+id/gesture_tip_layout" 
 android:layout_width="fill_parent" 
 android:layout_height="wrap_content" 
 android:layout_below="@id/top_layout" 
 android:orientation="vertical" 
 android:paddingtop="20dip" > 
 
 
 <textview 
  android:id="@+id/text_tip" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:layout_margintop="10dip" 
  android:gravity="center_horizontal" 
  android:textcolor="#000000" 
  android:visibility="invisible" /> 
 </linearlayout> 
 
 <framelayout 
 android:id="@+id/gesture_container" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:layout_below="@id/gesture_tip_layout" > 
 </framelayout> 
 
 
</relativelayout> 

验证密码的代码实现类
gestureverifyactivity

package com.wujay.fund; 
 
import com.wujay.fund.r; 
import com.wujay.fund.widget.gesturecontentview; 
import com.wujay.fund.widget.gesturedrawline.gesturecallback; 
import android.app.activity; 
import android.app.dialog; 
import android.content.dialoginterface; 
import android.content.dialoginterface.onclicklistener; 
import android.content.intent; 
import android.os.bundle; 
import android.text.html; 
import android.text.textutils; 
import android.view.keyevent; 
import android.view.view; 
import android.view.animation.animation; 
import android.view.animation.animationutils; 
import android.widget.framelayout; 
import android.widget.imageview; 
import android.widget.relativelayout; 
import android.widget.textview; 
import android.widget.toast; 
 
/** 
 * 手势绘制/校验界面 
 */ 
public class gestureverifyactivity extends activity{ 
 private textview mtexttip; 
 private framelayout mgesturecontainer; 
 private gesturecontentview mgesturecontentview; 
 
 @override 
 public void oncreate(bundle savedinstancestate) { 
 super.oncreate(savedinstancestate); 
 setcontentview(r.layout.activity_gesture_verify); 
 setupviews(); 
 } 
 
 
 private void setupviews() { 
 //验证失败的错误提示 
 mtexttip = (textview) findviewbyid(r.id.text_tip); 
 mgesturecontainer = (framelayout) findviewbyid(r.id.gesture_container); 
  
 // 初始化一个显示各个点的viewgroup 
 mgesturecontentview = new gesturecontentview(this, true, "12589", 
  new gesturecallback() { 
 
   @override 
   public void ongesturecodeinput(string inputcode) { 
 
   } 
 
   @override 
   public void checkedsuccess() { 
   mgesturecontentview.cleardrawlinestate(0l); 
   toast.maketext(gestureverifyactivity.this, "密码正确", 1000).show(); 
   gestureverifyactivity.this.finish(); 
   } 
 
   @override 
   public void checkedfail() { 
   mgesturecontentview.cleardrawlinestate(1300l); 
   mtexttip.setvisibility(view.visible); 
   mtexttip.settext(html 
    .fromhtml("<font color='#c70c1e'>密码错误</font>")); 
   // 左右移动动画 
   animation shakeanimation = animationutils.loadanimation(gestureverifyactivity.this, r.anim.shake); 
   mtexttip.startanimation(shakeanimation); 
   } 
  }); 
 // 设置手势解锁显示到哪个布局里面 
 mgesturecontentview.setparentview(mgesturecontainer); 
 } 
 
 
} 

shake.xml

<?xml version="1.0" encoding="utf-8"?> 
<translate xmlns:android="http://schemas.android.com/apk/res/android" 
android:fromxdelta="0" 
android:toxdelta="10" 
android:duration="120" 
android:interpolator="@android:anim/cycle_interpolator" 
android:repeatmode="restart" 
android:repeatcount="2"/> 

推荐文章:

android自定义ui手势密码简单版

android自定义ui手势密码改进版

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