Android自定义UI手势密码终结版
程序员文章站
2024-03-02 17:48:16
之前写过3篇的demo,不过没有集成到真实的企业项目中,这几天正好领到一个手势密码项目,昨天刚好弄完,今天抽空整理下,目前还没有完善,有一些地方需要更改,不过基本的流程都可...
之前写过3篇的demo,不过没有集成到真实的企业项目中,这几天正好领到一个手势密码项目,昨天刚好弄完,今天抽空整理下,目前还没有完善,有一些地方需要更改,不过基本的流程都可以跑通了。
源码下载地址:http://xiazai.jb51.net/201610/yuanma/androidgesturelock(jb51.net).rar
先看主界面的入口把、里面有2个button(一个是设置手势密码、一个是校验手势密码)
activity_main.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" tools:context="com.example.gesturelock.mainactivity" > <button android:id="@+id/setting" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_alignparenttop="true" android:text="设置" /> <button android:id="@+id/verify" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparenttop="true" android:layout_torightof="@+id/setting" android:text="校验" /> </relativelayout>
在看主界面的代码把
mainactivity
package com.example.gesturelock; import android.app.activity; import android.content.intent; import android.os.bundle; import android.view.menu; import android.view.menuitem; import android.view.view; import android.view.view.onclicklistener; import android.widget.button; public class mainactivity extends activity implements onclicklistener { private button setting, verify; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); setting = (button) findviewbyid(r.id.setting); verify = (button) findviewbyid(r.id.verify); setting.setonclicklistener(this); verify.setonclicklistener(this); } @override public void onclick(view v) { switch (v.getid()) { case r.id.setting: startactivity(new intent(this, gestureeditactivity.class)); break; case r.id.verify: startactivity(new intent(this, gestureverifyactivity.class)); break; default: break; } } }
想了想还是先贴数据库把---就是存放手势密码、以及还可以输入的手势密码次数
publicsqliteopenhelper
package com.example.gesturelock; import android.content.contentvalues; import android.content.context; import android.database.cursor; import android.database.sqlexception; import android.database.sqlite.sqlitedatabase; import android.database.sqlite.sqliteopenhelper; public class publicsqliteopenhelper extends sqliteopenhelper{ private static string name = "publicsqlite"; private static string gesture_password = "gesture_password"; private static final int version = 1; public sqlitedatabase db; public publicsqliteopenhelper(context context) { super(context, name, null, version); } @override public void oncreate(sqlitedatabase db) { string sqlpass = "create table " + "gesture_password"+ "(" + gesturepassword.wxid + " text not null," + gesturepassword.password + " text not null," + gesturepassword.remainopportunity + " text not null)"; db.execsql(sqlpass); } @override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { db.execsql("drop table if exists password"); oncreate(db); } public class gesturepassword { public static final string wxid = "wxid"; public static final string password = "password"; public static final string remainopportunity = "remainopportunity"; } /** * 插入手势密码表 */ public void insertgestureinfo(sqlitedatabase database ,string password,string times){ contentvalues values = null; try { values = new contentvalues(); values.put(gesturepassword.wxid, "001"); values.put(gesturepassword.password, password); values.put(gesturepassword.remainopportunity, ""+times); database.insert(publicsqliteopenhelper.gesture_password, null, values); } catch (exception e) { e.printstacktrace(); throw new sqlexception(e.getmessage()); }finally{ if (values != null) { values.clear(); values = null; } } } /** * 修改手势密码表---初始化次数为8次 * * */ public void updategestureinfo(sqlitedatabase database,string password,string times) { contentvalues values = null; try { if (password == null) { values = new contentvalues(); values.put(gesturepassword.wxid, "001"); values.put(gesturepassword.remainopportunity, ""+times); database.update(publicsqliteopenhelper.gesture_password, values, "wxid=?", new string[] { "001" }); }else { values = new contentvalues(); values.put(gesturepassword.wxid, "001"); values.put(gesturepassword.password, password); values.put(gesturepassword.remainopportunity, ""+times); database.update(publicsqliteopenhelper.gesture_password, values, "wxid=?", new string[] { "001" }); } } catch (sqlexception e) { } finally { if (values != null) { values.clear(); values = null; } } } /** * 查询手势密码表有无记录 * @return */ public boolean querygesturetablecount(sqlitedatabase database){ cursor cursor = null; try { cursor = database.query(publicsqliteopenhelper.gesture_password, null, null, null, null, null, null); if (cursor != null && cursor.getcount()>0) { return true; }else { return false; } } catch (exception e) { } finally{ if (cursor != null) { cursor.close(); cursor = null; } } return false; } /** * 查询手势密码表--查看剩余次数 * */ public string querygesturetime(sqlitedatabase database) { cursor cursor = null; try { cursor = database.query(publicsqliteopenhelper.gesture_password, null, null, null, null, null, null); if ((cursor != null) && (cursor.getcount() > 0)) { if (cursor.movetofirst()) { int columnindex = cursor .getcolumnindex(gesturepassword.remainopportunity); return cursor.getstring(columnindex); } } } catch (exception e) { } finally { if (cursor != null) { cursor.close(); cursor = null; } } return ""; } /** * 查询手势密码表--查看密码 * */ public string querygesturepassword(sqlitedatabase database) { cursor cursor = null; try { cursor = database.query(publicsqliteopenhelper.gesture_password, null, null, null, null, null, null); if ((cursor != null) && (cursor.getcount() > 0)) { if (cursor.movetofirst()) { int columnindex = cursor .getcolumnindex(gesturepassword.password); return cursor.getstring(columnindex); } } } catch (exception e) { } finally { if (cursor != null) { cursor.close(); cursor = null; } } return ""; } }
接下里再看工具类把--就是输入的手势密码简单md5加密、以及屏幕尺寸工具类
/** * */ package com.example.gesturelock; import android.content.context; import android.view.windowmanager; public class apputil { /** * 获取屏幕分辨�? * @param context * @return */ public static int[] getscreendispaly(context context) { windowmanager windowmanager = (windowmanager) context.getsystemservice(context.window_service); @suppresswarnings("deprecation") int width = windowmanager.getdefaultdisplay().getwidth(); @suppresswarnings("deprecation") int height = windowmanager.getdefaultdisplay().getheight(); int result[] = { width, height }; return result; } }
package com.example.gesturelock; import java.security.messagedigest; import java.security.nosuchalgorithmexception; import android.util.log; public class md5encodeutil { public static string md5ecode(string gesture){ log.i("gyl","gesture---"+gesture.tostring()); byte[] toencode=gesture.tostring().getbytes(); log.i("gyl","byte[]----"+toencode.tostring()); try{ messagedigest md5=messagedigest.getinstance("md5"); md5.reset(); md5.update(toencode); return hexencode(md5.digest()); }catch(nosuchalgorithmexception e){ e.printstacktrace(); } return ""; } public static string hexencode(byte[] toencode){ stringbuilder sb=new stringbuilder(toencode.length*2); for(byte b:toencode){ sb.append(integer.tohexstring((b&0xf0)>>>4)); sb.append(integer.tohexstring(b&0x0f)); } return sb.tostring().touppercase(); } }
一步步来,接下来看bean类,就是每个圆点的属性
constants
package com.example.gesturelock; 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; // 错误状态 }
gesturepoint
package com.example.gesturelock; import android.widget.imageview; public class gesturepoint { /** * 左边x的值 */ private int leftx; /** * 右边x的值 */ private int rightx; /** * 上边y的值 */ private int topy; /** * 下边y的值 */ private int bottomy; /** * 这个点对应的imageview控件 */ private imageview image; /** * 中心x值 */ private int centerx; /** * 中心y值 */ private int centery; /** * 状态值 */ private int pointstate; /** * 代表这个point对象代表的数字,从1开始(直接感觉从1开始) */ private int num; 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, int x, int y) { pointstate = state; switch (state) { case constants.point_state_normal: this.image.setbackgroundresource(r.drawable.gesturewhite); break; case constants.point_state_selected: // 以原点为圆心,右下为正,左上为负 if (y == 0 && x > 0) { this.image.setbackgroundresource(r.drawable.blueright); } else if (y == 0 && x < 0) { this.image.setbackgroundresource(r.drawable.blueleft); } else if (x == 0 && y > 0) { this.image.setbackgroundresource(r.drawable.bluedown); } else if (x == 0 && y < 0) { this.image.setbackgroundresource(r.drawable.blueup); } else if (x > 0 && y > 0) { this.image.setbackgroundresource(r.drawable.bluerightdown); } else if (x < 0 && y < 0) { this.image.setbackgroundresource(r.drawable.blueleftup); } else if (x < 0 && y > 0) { this.image.setbackgroundresource(r.drawable.blueleftdown); } else if (x > 0 && y < 0) { this.image.setbackgroundresource(r.drawable.bluerightup); } else if (x == 0 && y == 0) { this.image.setbackgroundresource(r.drawable.bluedot); } break; case constants.point_state_wrong: if (y == 0 && x > 0) { this.image.setbackgroundresource(r.drawable.redright); } else if (y == 0 && x < 0) { this.image.setbackgroundresource(r.drawable.redleft); } else if (x == 0 && y > 0) { this.image.setbackgroundresource(r.drawable.reddown); } else if (x == 0 && y < 0) { this.image.setbackgroundresource(r.drawable.redup); } else if (x > 0 && y > 0) { this.image.setbackgroundresource(r.drawable.redrightdown); } else if (x < 0 && y < 0) { this.image.setbackgroundresource(r.drawable.redleftup); } else if (x < 0 && y > 0) { this.image.setbackgroundresource(r.drawable.redleftdown); } else if (x > 0 && y < 0) { this.image.setbackgroundresource(r.drawable.redrightup); } else if (x == 0 && y == 0) { this.image.setbackgroundresource(r.drawable.reddot); } 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 + "]"; } }
接下来就看那9个点的绘制界面
gesturecontentview
package com.example.gesturelock; import java.util.arraylist; import java.util.list; import com.example.gesturelock.gesturedrawline.gesturecallback; import android.content.context; import android.view.view; import android.view.viewgroup; import android.widget.imageview; /** * 手势密码容器类 * */ public class gesturecontentview extends viewgroup { /** * 每个点区域的宽度 */ private int blockwidth; private int spacing ; /** * 声明一个集合用来封装坐标集合 */ private list<gesturepoint> list; private context context; private gesturedrawline gesturedrawline; /** * 包含9个imageview的容器,初始化 * @param context * @param isverify 是否为校验手势密码 * @param password 用户传入密码 * @param callback 手势绘制完毕的回调 */ public gesturecontentview(context context, boolean isverify,string password, gesturecallback callback) { super(context); this.blockwidth = dip2px(context,66f); //圆圈的直径dp值 this.spacing = dip2px(context, 30f); //圆圈之间的距离dp值 this.list = new arraylist<gesturepoint>(); this.context = context; // 添加9个图标 addchild(); // 初始化一个可以画线的view gesturedrawline = new gesturedrawline(context, list, isverify,password, callback); } public static int dip2px(context context, float dpvalue) { // todo auto-generated method stub final float scale = context.getresources().getdisplaymetrics().density; return (int) (dpvalue * scale + 0.5f); } private void addchild(){ for (int i = 0; i < 9; i++) { imageview image = new imageview(context); image.setbackgroundresource(r.drawable.gesturewhite); this.addview(image,new layoutparams(blockwidth, blockwidth)); invalidate(); // 第几行 int row = i / 3; // 第几列 int col = i % 3; // 定义点的每个属性 int leftx = col * blockwidth + col * spacing; int topy = row * blockwidth + row * spacing; int rightx = leftx + blockwidth; int bottomy = topy + blockwidth; //圆圈之间线的位置 gesturepoint p = new gesturepoint(leftx, rightx, topy, bottomy, image,i+1); this.list.add(p); } } public void setparentview(viewgroup parent){ // 得到屏幕的宽度 layoutparams layoutparams = new layoutparams(blockwidth * 3 + spacing * 2, blockwidth * 3 + spacing * 2); parent.addview(gesturedrawline,layoutparams); parent.addview(this,layoutparams); } @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); //用于绘制圆圈的位置,d表示x轴方向的偏移量,如果要上下移动整块手绘区域,则将top和bottom参数增加或减小一个合适的偏移量 int leftx = col * blockwidth + col * spacing; int topy = row * blockwidth + row * spacing; int rightx = leftx + blockwidth; int bottomy = topy + blockwidth; v.layout(leftx, topy, rightx, bottomy) ; } } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); } /** * 保留路径delaytime时间长 * @param delaytime */ public void cleardrawlinestate(long delaytime) { gesturedrawline.cleardrawlinestate(delaytime); } }
然后继续看当手指连接时候,的那个绘制中间连线的代码
gesturedrawline
package com.example.gesturelock; import java.util.arraylist; import java.util.hashmap; import java.util.list; import java.util.map; import android.annotation.suppresslint; import android.content.context; import android.graphics.bitmap; import android.graphics.bitmapfactory; 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; /** * 手势密码路径绘制 * */ public class gesturedrawline extends view { private int mov_x;// 声明起点坐标 private int mov_y; private paint paint;// 声明画笔 private canvas canvas;// 画布 private bitmap bitmap;// 位图 private list<gesturepoint> list;// private list<pair<gesturepoint, gesturepoint>> linelist;// 记录画过的线 private map<string, gesturepoint> autocheckpointmap;// 自动选中的情况点 private boolean isdrawenable = true; // 是否允许绘制 /** * 屏幕的宽度和高度 */ private int[] screendispaly; private gesturepoint currentpoint; private gesturecallback callback; private stringbuilder passwordsb; private boolean isverify; private string password; 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(15);// paint.setcolor(getresources().getcolor(r.color.gestureline_green));// 设置默认连线颜色 paint.setantialias(true); //9个点的集合 this.list = list; //画过的线集合 this.linelist = new arraylist<pair<gesturepoint, gesturepoint>>(); initautocheckpointmap(); this.callback = callback; this.isverify = isverify; this.password = password; //密码集 this.passwordsb = new stringbuilder(); } 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, null); } // 触摸事件 @suppresslint("clickableviewaccessibility") @override public boolean ontouchevent(motionevent event) { if (isdrawenable == false) { return true; } // 设置默认连线颜色 paint.setcolor(getresources().getcolor(r.color.gestureline_green)); switch (event.getaction()) { case motionevent.action_down: 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, 0, 0); passwordsb.append(currentpoint.getnum()); } invalidate(); //回调方法 callback.onpointdown() ; break; case motionevent.action_move: //清楚痕迹 clearscreenanddrawlist(); //移动回调 callback.ongesturelinemove(); //获取移动到的位置的点位 gesturepoint pointat = getpointat((int) event.getx(), (int) event.gety()); if (currentpoint == null && pointat == null) { return true; } else { //由间隔处滑到原点处 if (currentpoint == null && pointat != null) { // 如果为空,那么把手指移动到的点赋值给currentpoint currentpoint = pointat; /**设置按下的点位的状态,保存密码*/ currentpoint.setpointstate(constants.point_state_selected, 0, 0); passwordsb.append(currentpoint.getnum()); } } /***/ if (pointat == null || currentpoint.equals(pointat) || constants.point_state_selected == pointat .getpointstate()) { canvas.drawline(currentpoint.getcenterx(), currentpoint.getcentery(), event.getx(), event.gety(), paint); } else { int x = pointat.getcenterx() - currentpoint.getcenterx(); int y = pointat.getcentery() - currentpoint.getcentery(); currentpoint .setpointstate(constants.point_state_selected, x, y); if (pointat.equals(list.get(list.size() - 1))) { pointat .setpointstate(constants.point_state_selected, 0, 0); } 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,0, 0); currentpoint = pointat; } else { pair<gesturepoint, gesturepoint> pair = new pair<gesturepoint, gesturepoint>( currentpoint, pointat); linelist.add(pair); passwordsb.append(pointat.getnum()); currentpoint = pointat; } } invalidate(); break; case motionevent.action_up: isdrawenable = false; if (isverify) { // 手势密码校验 string encodestring=md5encodeutil.md5ecode(string.valueof( passwordsb)); string passwordmd5ecode = md5encodeutil.md5ecode(password); if (passwordmd5ecode.equals(encodestring)) { callback.checkedsuccess(); } else { log.e("tag", "encode string fali"); callback.checkedfail(); } } else { //重新绘制界面 clearscreenanddrawlist(); gesturepoint pointatup = getpointat((int) event.getx(), (int) event.gety()); if (pointatup != null && currentpoint.equals(pointatup) && constants.point_state_selected == pointatup .getpointstate()&&passwordsb.length()==1) { currentpoint.setpointstate(constants.point_state_wrong, 0, 0); } invalidate(); callback.ongesturecodeinput(passwordsb.tostring()); } break; default: break; } return true; } /** * * @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, 0, 0); } invalidate(); isdrawenable = true; } } /** * * @param x * @param y */ 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 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 void clearscreenanddrawlist() { canvas.drawcolor(color.transparent, porterduff.mode.clear); for (int i = 0; i < linelist.size(); i++) { int r = 0,x,y; if ((linelist.get(i).first.gettopy() - linelist.get(i).first.getbottomy()) / 2 < 0) r = -(linelist.get(i).first.gettopy() - linelist.get(i).first.getbottomy()) / 2; else { r = (linelist.get(i).first.gettopy() - linelist.get(i).first.getbottomy()) / 2; } float d = (float) 0.707 * r; x = linelist.get(i).second.getcenterx() -linelist.get(i).first.getcenterx(); y = linelist.get(i).second.getcentery() -linelist.get(i).first.getcentery(); if (i == linelist.size() - 1) { linelist.get(i).second.setpointstate(constants.point_state_selected, 0, 0); linelist.get(i).first.setpointstate(constants.point_state_selected, x, y); } else { linelist.get(i).first.setpointstate(constants.point_state_selected, x, y); linelist.get(i).second.setpointstate(constants.point_state_selected, x, y); } if (y == 0 && x > 0) { canvas.drawline(linelist.get(i).first.getcenterx() + r, linelist.get(i).first.getcentery(), linelist.get(i).second.getcenterx() - r, linelist.get(i).second.getcentery(), paint);// 画线 } else if (y == 0 && x < 0 ) { canvas.drawline(linelist.get(i).first.getcenterx() - r, linelist.get(i).first.getcentery(), linelist.get(i).second.getcenterx() + r, linelist.get(i).second.getcentery(), paint);// 画线 }else if (x == 0 && y > 0){ canvas.drawline(linelist.get(i).first.getcenterx(), linelist.get(i).first.getcentery() + r, linelist.get(i).second.getcenterx(), linelist.get(i).second.getcentery() - r, paint);// 画线 }else if (x == 0 && y < 0 ) { canvas.drawline(linelist.get(i).first.getcenterx(), linelist.get(i).first.getcentery() - r, linelist.get(i).second.getcenterx() , linelist.get(i).second.getcentery() + r, paint);// 画线 } else if( x > 0 && y > 0 ){ canvas.drawline(linelist.get(i).first.getcenterx() + d, linelist.get(i).first.getcentery() + d, linelist.get(i).second.getcenterx() - d , linelist.get(i).second.getcentery() - d, paint);// 画线 }else if(x > 0 && y < 0 ) { canvas.drawline(linelist.get(i).first.getcenterx() + d, linelist.get(i).first.getcentery() - d, linelist.get(i).second.getcenterx()-d , linelist.get(i).second.getcentery() + d, paint);// 画线 } else if (x < 0 && y > 0){ canvas.drawline(linelist.get(i).first.getcenterx() - d, linelist.get(i).first.getcentery() + d, linelist.get(i).second.getcenterx()+d , linelist.get(i).second.getcentery() - d, paint);// 画线 } else if(x < 0 && y < 0 ) { canvas.drawline(linelist.get(i).first.getcenterx() - d, linelist.get(i).first.getcentery() - d, linelist.get(i).second.getcenterx()+d , linelist.get(i).second.getcentery() + d, paint);// 画线 } } } private void drawerrorpathtip() { canvas.drawcolor(color.transparent, porterduff.mode.clear); paint.setcolor(getresources().getcolor(r.color.gestureline_red));// 设置默认线路颜色 if(linelist.size() == 0 && currentpoint!= null){ currentpoint.setpointstate(constants.point_state_wrong, 0, 0); } for (int i = 0; i < linelist.size(); i++) { int r = 0,x,y; if ((linelist.get(i).first.gettopy() - linelist.get(i).first.getbottomy()) / 2 < 0) r = -(linelist.get(i).first.gettopy() - linelist.get(i).first.getbottomy()) / 2; else { r = (linelist.get(i).first.gettopy() - linelist.get(i).first.getbottomy()) / 2; } float d = (float) 0.707 * r; x = linelist.get(i).second.getcenterx() -linelist.get(i).first.getcenterx(); y = linelist.get(i).second.getcentery() -linelist.get(i).first.getcentery(); if (i == linelist.size() - 1) { linelist.get(i).second.setpointstate(constants.point_state_wrong, 0, 0); linelist.get(i).first.setpointstate(constants.point_state_wrong, x, y); } else { linelist.get(i).first.setpointstate(constants.point_state_wrong, x, y); linelist.get(i).second.setpointstate(constants.point_state_wrong, x, y); } if (y == 0 && x > 0) { canvas.drawline(linelist.get(i).first.getcenterx() + r, linelist.get(i).first.getcentery(), linelist.get(i).second.getcenterx() - r, linelist.get(i).second.getcentery(), paint);// 画线 } else if (y == 0 && x < 0 ) { canvas.drawline(linelist.get(i).first.getcenterx() - r, linelist.get(i).first.getcentery(), linelist.get(i).second.getcenterx() + r, linelist.get(i).second.getcentery(), paint);// 画线 }else if (x == 0 && y > 0){ canvas.drawline(linelist.get(i).first.getcenterx(), linelist.get(i).first.getcentery() + r, linelist.get(i).second.getcenterx(), linelist.get(i).second.getcentery() - r, paint);// 画线 }else if (x == 0 && y < 0 ) { canvas.drawline(linelist.get(i).first.getcenterx(), linelist.get(i).first.getcentery() - r, linelist.get(i).second.getcenterx() , linelist.get(i).second.getcentery() + r, paint);// 画线 } else if( x > 0 && y > 0 ){ canvas.drawline(linelist.get(i).first.getcenterx() + d, linelist.get(i).first.getcentery() + d, linelist.get(i).second.getcenterx() - d , linelist.get(i).second.getcentery() - d, paint);// 画线 }else if(x > 0 && y < 0 ) { canvas.drawline(linelist.get(i).first.getcenterx() + d, linelist.get(i).first.getcentery() - d, linelist.get(i).second.getcenterx()-d , linelist.get(i).second.getcentery() + d, paint);// 画线 } else if (x < 0 && y > 0){ canvas.drawline(linelist.get(i).first.getcenterx() - d, linelist.get(i).first.getcentery() + d, linelist.get(i).second.getcenterx()+d , linelist.get(i).second.getcentery() - d, paint);// 画线 } else if(x < 0 && y < 0 ) { canvas.drawline(linelist.get(i).first.getcenterx() - d, linelist.get(i).first.getcentery() - d, linelist.get(i).second.getcenterx()+d , linelist.get(i).second.getcentery() + d, paint);// 画线 } } invalidate(); } public interface gesturecallback { public abstract void ongesturecodeinput(string inputcode); public abstract void checkedsuccess(); public abstract void checkedfail(); public abstract void ongesturelinemove(); public abstract void onpointdown() ; } }
ok 注备工作进行完毕,接下来看设置手势密码界面
gesture_edit.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#f2f2f2" > <linearlayout android:id="@+id/ll_head" android:layout_width="fill_parent" android:layout_height="48dp" android:background="@drawable/bg_head" android:gravity="center_vertical" android:orientation="horizontal" > <linearlayout android:id="@+id/ll_head_left" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_margintop="1dp" android:gravity="center_vertical" android:background="@drawable/selector_head_back" android:orientation="horizontal" > <imageview android:id="@+id/im_back" android:layout_width="7dp" android:layout_height="14dp" android:layout_marginleft="5dp" android:background="@drawable/back" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="5dp" android:text="@string/set_gesture_code" android:textcolor="#fff" android:textsize="17.33dp" /> </linearlayout> <view android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="1" /> </linearlayout> <linearlayout android:id="@+id/gesture_tip_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margintop="75.67dp" android:orientation="vertical" > <textview android:id="@+id/tv_edit_texttip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@string/set_gesture_pattern" android:textcolor="@color/color_black" android:textsize="@dimen/textsize_s3" /> </linearlayout> <relativelayout android:id="@+id/fl_edit_gesture_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="48dp" android:gravity="center_horizontal" > </relativelayout> </linearlayout>
gestureeditactivity
package com.example.gesturelock; import android.app.activity; import android.database.sqlite.sqlitedatabase; import android.os.bundle; import android.os.handler; import android.text.textutils; import android.view.view; import android.view.view.onclicklistener; import android.widget.linearlayout; import android.widget.relativelayout; import android.widget.textview; import com.example.gesturelock.gesturedrawline.gesturecallback; public class gestureeditactivity extends activity implements onclicklistener { private linearlayout im_back; private textview tv_texttip; private relativelayout mgesturecontainer; private gesturecontentview mgesturecontentview; // 第一次输入的密码 private string mfirstpassword = null; // 是不是第一次输入 private boolean misfirstinput = true; static final string tables_name_gesture = "gesture_password"; public final static int gesture_time = 8; private publicsqliteopenhelper sqliteinstance; private sqlitedatabase database; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.gesture_edit); // 错误提示 tv_texttip = (textview) findviewbyid(r.id.tv_edit_texttip); // 9点区域 mgesturecontainer = (relativelayout) findviewbyid(r.id.fl_edit_gesture_container); // 返回 im_back = (linearlayout) findviewbyid(r.id.ll_head_left); // 初始化继续不可点击 im_back.setonclicklistener(this); mgesturecontentview = new gesturecontentview(this, false, "", new gesturecallback() { @override public void ongesturecodeinput(string inputcode) { if (misfirstinput) { // 第一次输入手势密码 if (!isinputpassvalidate(inputcode)) { // 至少连接4个点 tv_texttip.settext(getresources().getstring( r.string.drawguesturewarning)); // 2秒后清除界面 mgesturecontentview.cleardrawlinestate(2000l); // 2秒后还原提示 mhandler.postdelayed(connect4dot, 2000); return; }else { mfirstpassword = inputcode; tv_texttip.settext(getresources().getstring( r.string.drawguestureagain)); mhandler.postdelayed(cleargreenline, 1000); misfirstinput = false; } } else { if (inputcode.equals(mfirstpassword)) { // 第二次输入手势密码与第一次一致 tv_texttip.settext(getresources().getstring( r.string.your_gesture_code)); sqliteinstance = new publicsqliteopenhelper(gestureeditactivity.this); database = sqliteinstance.getwritabledatabase(); boolean count = sqliteinstance.querygesturetablecount(database); if (count) { //如果有记录 sqliteinstance.updategestureinfo(database,mfirstpassword, "8"); }else { //如果没有记录 sqliteinstance.insertgestureinfo(database,mfirstpassword, "8"); } mhandler.postdelayed(setgestureokfinish, 1000); } else { if (!isinputpassvalidate(inputcode)) { // 至少连接4个点 tv_texttip.settext(getresources().getstring( r.string.drawguesturewarning)); // 2秒后清除界面 mgesturecontentview.cleardrawlinestate(2000l); // 2秒后还原提示 mhandler.postdelayed(connect4dot, 2000); } else { // 第二次输入手势密码与第一次不一致 tv_texttip.settext(getresources() .getstring(r.string.drawagain)); // 左右移动动画 // animation shakeanimation = // animationutils.loadanimation(gestureeditactivity.this,r.anim.shake); // tv_texttip.startanimation(shakeanimation); // 保持绘制的线,1.5秒后清除 mgesturecontentview .cleardrawlinestate(2000l); mhandler.postdelayed(changetext2again, 2000); } } } } @override public void checkedfail() { } @override public void ongesturelinemove() { tv_texttip.settext(getresources().getstring( r.string.release_hande_when_finish)); } @override public void onpointdown() { } @override public void checkedsuccess() { } }); // 设置手势解锁显示到哪个布局里面 mgesturecontentview.setparentview(mgesturecontainer); } @override protected void onresume() { super.onresume(); } handler mhandler = new handler(); runnable cleargreenline = new runnable() { public void run() { mgesturecontentview.cleardrawlinestate(0l); } }; runnable connect4dot = new runnable() { public void run() { tv_texttip.settext(getresources().getstring( r.string.set_gesture_pattern)); } }; runnable setgestureokfinish = new runnable() { public void run() { finish(); } }; runnable changetext2again = new runnable() { public void run() { tv_texttip.settext(getresources().getstring( r.string.drawguestureagain)); } }; private boolean isinputpassvalidate(string inputpassword) { if (textutils.isempty(inputpassword) || inputpassword.length() < 4) { return false; } return true; } protected void ondestroy() { super.ondestroy(); } @override public void onclick(view v) { switch (v.getid()) { case r.id.ll_head_left: finish(); break; } } }
最后看校验界面
gesture_verify.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent" android:background="@color/color_main" > <linearlayout android:id="@+id/ll_head" android:layout_width="fill_parent" android:layout_height="48dp" android:background="@drawable/bg_head" android:gravity="center_vertical" android:orientation="horizontal" > <linearlayout android:id="@+id/ll_head_left" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_margintop="1dp" android:gravity="center_vertical" android:background="@drawable/selector_head_back" android:orientation="horizontal" > <imageview android:id="@+id/im_back" android:layout_width="7dp" android:layout_height="14dp" android:layout_marginleft="5dp" android:background="@drawable/back" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="5dp" android:text="@string/verify_gesture_code" android:textcolor="#fff" android:textsize="17.33dp" /> </linearlayout> <view android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="1" /> </linearlayout> <linearlayout android:id="@+id/gesture_tip_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margintop="75.67dp" android:orientation="vertical" > <textview android:id="@+id/tv_edit_texttip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@string/set_gesture_pattern" android:textcolor="@color/color_black" android:textsize="@dimen/textsize_s3" /> </linearlayout> <relativelayout android:id="@+id/fl_verify_gesture_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="48dp" android:gravity="center_horizontal" > </relativelayout> </linearlayout>
最后校验代码
package com.example.gesturelock; import java.util.timer; import java.util.timertask; import android.annotation.suppresslint; import android.app.activity; import android.content.intent; import android.database.sqlite.sqlitedatabase; import android.os.bundle; import android.os.handler; import android.os.message; import android.text.textutils; import android.util.log; import android.view.view; import android.widget.linearlayout; import android.widget.relativelayout; import android.widget.textview; import com.example.gesturelock.gesturedrawline.gesturecallback; public class gestureverifyactivity extends activity { private static string tag = "gestureverifyactivity"; private textview tv_texttip; private relativelayout mgesturecontainer; private linearlayout ib_back; private gesturecontentview mgesturecontentview; private timer timer = new timer() ; private timertask closeactivitytask = null; static final string tables_name_gesture = "gesture_password"; private int remainopportunity ; private publicsqliteopenhelper sqliteinstance; private sqlitedatabase database; private void resetcloseevent(){ clearcloseevent() ; closeactivitytask = new timertask() { public void run() { message message = new message(); message.what = 1; handler.sendmessage(message); } }; timer.schedule(closeactivitytask, 30000); } private void clearcloseevent(){ if(closeactivitytask != null){ closeactivitytask.cancel() ; closeactivitytask = null ; log.i(tag, "----------closeactivitytask----------"+closeactivitytask); } } public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.gesture_verify); resetcloseevent(); tv_texttip = (textview) findviewbyid(r.id.tv_edit_texttip); ib_back = (linearlayout) findviewbyid(r.id.ll_head_left); mgesturecontainer = (relativelayout) findviewbyid(r.id.fl_verify_gesture_container); sqliteinstance = new publicsqliteopenhelper(gestureverifyactivity.this); database = sqliteinstance.getwritabledatabase(); //从数据库中获取手势密码、剩余次数 firstpassward = sqliteinstance.querygesturepassword(database); remainopportunitystr = sqliteinstance.querygesturetime(database); if (textutils.isempty(remainopportunitystr)) { remainopportunity = 8; //初始化8次 sqliteinstance.updategestureinfo(database,null, "8"); } else { remainopportunity = integer.parseint(remainopportunitystr); } if(remainopportunity == 0){ tv_texttip.settextcolor(getresources().getcolor(r.color.gestureline_red)); tv_texttip.settext(getresources().getstring(r.string.no_chance)); } ib_back.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { finish(); } }); mgesturecontentview = new gesturecontentview(this, true, firstpassward, new gesturecallback() { @override public void ongesturecodeinput(string inputcode) { } @suppresslint("showtoast") @override public void checkedsuccess() { sqliteinstance.updategestureinfo(database,null, "8"); mgesturecontentview.cleardrawlinestate(0l); resetcloseevent(); finish(); //发送广播 sendbroadcast(new intent("com.godinsec.seland.intent.casintent.intent_load_sd")); } @override public void checkedfail() { mgesturecontentview.cleardrawlinestate(2000l); tv_texttip.settextcolor(getresources().getcolor(r.color.gestureline_red)); if(remainopportunity > 0){ remainopportunity-- ; } sqliteinstance.updategestureinfo(database,null, ""+remainopportunity); resetcloseevent(); changetext(); } @override public void ongesturelinemove() { if(remainopportunity > 0){ tv_texttip.settextcolor(getresources().getcolor(r.color.textcolor_black_bb)); tv_texttip.settext(getresources().getstring(r.string.release_hande_when_finish)); } } @override public void onpointdown() { clearcloseevent() ; } }); mgesturecontentview.setparentview(mgesturecontainer); } protected void changetext() { log.e("tagg", "changetext"); if (remainopportunity == 7) { tv_texttip.settext(getresources().getstring( r.string.wrong_answer_seven)); } else if (remainopportunity == 6) { tv_texttip.settext(getresources().getstring( r.string.wrong_answer_six)); } else if (remainopportunity == 5) { tv_texttip.settext(getresources().getstring( r.string.wrong_answer_five)); } else if (remainopportunity == 4) { tv_texttip.settext(getresources().getstring( r.string.wrong_answer_four)); } else if (remainopportunity == 3) { tv_texttip.settext(getresources().getstring( r.string.wrong_answer_three)); } else if (remainopportunity == 2) { tv_texttip.settext(getresources().getstring( r.string.wrong_answer_two)); } else if (remainopportunity == 1) { tv_texttip.settext(getresources().getstring( r.string.wrong_answer_one)); } else { tv_texttip.settext(getresources().getstring( r.string.wrong_answer_zero)); handler.postdelayed(errorfinish, 2000); } } @override protected void onresume() { super.onresume(); } runnable errorfinish = new runnable() { public void run() { finish(); } }; @suppresslint("handlerleak") handler handler = new handler() { @override public void handlemessage(message msg) { super.handlemessage(msg); switch (msg.what) { case 1: finish(); break; } } }; private string remainopportunitystr; private string firstpassward; protected void ondestroy() { super.ondestroy(); } protected void onstop() { super.onstop(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Android自定义UI手势密码终结版
-
Android自定义UI手势密码改进版源码下载
-
Android自定义UI手势密码改进版
-
Android自定义UI实现微信语音
-
Android 自定义输入支付密码的软键盘实例代码
-
Android UI设计系列之自定义Dialog实现各种风格的对话框效果(7)
-
Android UI设计系列之自定义ListView仿QQ空间阻尼下拉刷新和渐变菜单栏效果(8)
-
Android 自定义View 密码框实例代码
-
Android UI设计系列之自定义TextView属性实现带下划线的文本框(4)
-
Android UI设计系列之自定义SwitchButton开关实现类似IOS中UISwitch的动画效果(2)