当前位置: 移动技术网 > IT编程>移动开发>Android > Android自定义UI手势密码改进版源码下载

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

西游降魔篇 影音,翟鸿枭,横穿马路 成俊

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

源码下载:

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

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手势密码改进版

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网