基于Android的图案解锁实现
来源:互联网 发布:四海金戈 全武将数据 编辑:程序博客网 时间:2024/04/29 20:56
备注说明:通过之前的“Android图案解锁”学习,特意将实现的思路给理出来、记录下来,作为自己的学习总结。文中存在不对之处,请大家踊跃指出,转载请标明出处。
实现思路:
1、自定义LockPatterView控件,定义九宫格点的类型,实现绘制九宫格布局。
2、重写onTouchEvent()事件,完成选中点的绘制。
3、绘制两点之间的连接线。
4、图案密码的设置与验证。
效果展示:
一、自定义LockPatterView控件,定义九宫格点的类型,实现绘制九宫格布局。
1、定义九宫格中的点类型。
/**自定义九宫格点类型*/ public class Point{ public static final int STATE_NORMAL=0;//正常时 public static final int STATE_PRESS=1;//选中时 public static final int STATE_ERROR=2;//错误时 public float x,y;//点的坐标 public int state;//点的状态 public Point(float x,float y){ this.x=x; this.y=y; } }
2、初始化九宫格的点坐标
/**初始化点的数据*/ private void initPoints() { //1.得到控件的布局 float width=getWidth(); float height=getHeight(); //2.得到横竖屏时的偏移量 if(width>height){//横屏时,高度充满整个控件 offsetX=(width-height)/2;//宽度居于控件中央显示 offsetY=0; width=height; }else{//竖屏时,宽度充满整个控件的宽度 offsetX=0; offsetY=(width-height)/2;//高度居于控件中央显示 height=width; } //图片资源 bitmap_normal = BitmapFactory.decodeResource(getResources(), R.drawable.ic_point_normal); bitmap_pressed = BitmapFactory.decodeResource(getResources(), R.drawable.ic_point_press); bitmap_error = BitmapFactory.decodeResource(getResources(), R.drawable.ic_point_error); bitmap_line = BitmapFactory.decodeResource(getResources(), R.drawable.ic_line_normal); bitmap_line_error = BitmapFactory.decodeResource(getResources(), R.drawable.ic_line_error); //3.初始化九宫格点的坐标 for(int i=0;i<points.length;i++){ for(int j=0;j<points[i].length;j++){ points[i][j]=new Point(width/4+j*width/4+offsetX,height/4+height/4*i+offsetY); } } isInit=true; }
3、将九宫格点绘制到画布上
/**将点画在画布上*/ private void points2Canvas(Canvas canvas) { // TODO Auto-generated method stub //3.绘制九宫格点 for(int i=0;i<points.length;i++){ for(int j=0;j<points[i].length;j++){ Point point=points[i][j]; if(point.state==Point.STATE_NORMAL){ canvas.drawBitmap(bitmap_normal, point.x-bitmap_normal.getWidth()/2, point.y-bitmap_normal.getHeight()/2, paint); }else if(point.state==Point.STATE_PRESS){ canvas.drawBitmap(bitmap_pressed, point.x-bitmap_pressed.getWidth()/2, point.y-bitmap_pressed.getHeight()/2, paint); }else{ canvas.drawBitmap(bitmap_error, point.x-bitmap_error.getWidth()/2, point.y-bitmap_error.getHeight()/2, paint); } } } }
4、最终效果
二、重写onTouchEvent()事件,完成选中点的绘制。
1、判断移动的点是否属于九宫格的点,如果是,则该点属于选中的点。
/**判断两点是否重合*/ public static boolean with(float pointX,float pointY,float r,float moveX,float moveY){ return Math.sqrt((pointX-moveX)*(pointX-moveX)+(pointY-moveY)*(pointY-moveY))<r; } /**检查移动的点是否属于九宫格的点*/ private Point checkPoints(){ for(int i=0;i<points.length;i++){ for(int j=0;j<points[i].length;j++){ Point point=points[i][j]; if(Point.with(point.x, point.y, bitmap_normal.getWidth()/2, moveX, moveY)){ return point; } } } return null; }
2、判断该点是否属于交叉点(之前已经添加过的点)。
/**检查是否是交叉点*/ private boolean crossPoint(Point point){ return pointList.contains(point); }
3、完成选中点的添加。
private float moveX,moveY;//移动点的坐标 private boolean isSelect,isFinish; private List<Point>pointList=new ArrayList<LockPatterView.Point>(); private static final int mMinPointCount=5;//最少绘制点数@Override public boolean onTouchEvent(MotionEvent event) { moveX=event.getX(); moveY=event.getY(); isFinish=false; Point point=null; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: resetPoints(); point=checkPoints(); if(point!=null){ isSelect=true; } break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: isFinish=true; isSelect=false; break; } //添加点 if(!isFinish&&isSelect&&point!=null){ if(crossPoint(point)){//是交叉点 }else{//新点 point.state=Point.STATE_PRESS; pointList.add(point); } } //绘制结束 if(isFinish){ if(pointList.size()==1){//只绘制一个点 resetPoints(); }else if(pointList.size()<mMinPointCount){//小于5个点时 errorPoints(); }else{//正确的点,用于之后作为密码使用 } } postInvalidate();//通知onDraw()方法,重新绘制 return true;//触摸事件能够继续执行下去 }
4、最终效果。
三、绘制两点之间的连线。
1、设置连接线的缩放。
/**判断两点之间的距离*/ public static double distance(Point a,Point b){ return Math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } //得到线的长度 float linelength=(float) Point.distance(a, b);if(a.state==Point.STATE_PRESS){ //设置线的缩放 matrix.setScale(linelength / bitmap_line.getWidth(), 1); //设置线的起始位置 matrix.postTranslate(a.x - bitmap_line.getWidth() / 2 , a.y - bitmap_line.getHeight() /2); canvas.drawBitmap(bitmap_line, matrix, paint); }else{ matrix.setScale(linelength / bitmap_line.getWidth(), 1); matrix.postTranslate(a.x - bitmap_line.getWidth() / 2 , a.y - bitmap_line.getHeight() /2); canvas.drawBitmap(bitmap_line_error, matrix, paint); }
2、得到线的旋转角度
// 获取角度 public float getDegrees(Point pointA, Point pointB) { return (float) Math.toDegrees(Math.atan2(pointB.y - pointA.y, pointB.x - pointA.x)); }
3、根据线的旋转角度以及线的长度,绘制出两点之间的连线。
/**画两点之间的连线*/ private void line2Canvas(Point a,Point b,Canvas canvas) { // TODO Auto-generated method stub //得到线的长度 float linelength=(float) Point.distance(a, b); float degress = getDegrees(a,b); canvas.rotate(degress, a.x, a.y); if(a.state==Point.STATE_PRESS){ //设置线的缩放 matrix.setScale(linelength / bitmap_line.getWidth(), 1); //设置线的起始位置 matrix.postTranslate(a.x - bitmap_line.getWidth() / 2 , a.y - bitmap_line.getHeight() /2); canvas.drawBitmap(bitmap_line, matrix, paint); }else{ matrix.setScale(linelength / bitmap_line.getWidth(), 1); matrix.postTranslate(a.x - bitmap_line.getWidth() / 2 , a.y - bitmap_line.getHeight() /2); canvas.drawBitmap(bitmap_line_error, matrix, paint); } canvas.rotate(-degress, a.x, a.y); }
4、在交叉点或移动线的时候也需要绘制连接线。
//画线 if(pointList.size()>0){ Point a=pointList.get(0); for(int i=1;i<pointList.size();i++){ Point b=pointList.get(i); line2Canvas(a,b,canvas); a=b; } if(isMoveNoPoint){//交叉点,连接线的时候 line2Canvas(a,new Point(moveX,moveY),canvas); } }
5、最终效果
四、图案密码的设置与验证。
1、初始化密码参数。
//初始化密码参数 int index = 1; for(int i=0;i<points.length;i++){ for(int j=0;j<points[i].length;j++){ Point point=points[i][j]; point.index = index; index++; } }
2、绘制图案后,设置密码。
String passwordStr=""; for(int i=0;i<pointList.size();i++){ passwordStr+=pointList.get(i).index; }
3、设置密码回调监听
/** * 图案监听器 */ public static interface OnPatterChangeLister{ void onPatterChange(String passwordStr); void onPatterStart(boolean isStart); } /** * 设置图案监听器 * @param changeLister */ public void SetOnPatterChangeLister(OnPatterChangeLister changeLister){ if (changeLister != null) { this.onPatterChangeLister = changeLister; } }
4、对绘制正确、绘制错误时设置图案监听返回。
//绘制结束 if(isFinis){ if(pointList.size()==1){ resetPoint(); }else if(pointList.size()<POINT_SIZE&&pointList.size()>0){ errorPoint(); onPatterChangeLister.onPatterChange(null); }else{ if(onPatterChangeLister!=null){ String passwordStr=""; for(int i=0;i<pointList.size();i++){ passwordStr+=pointList.get(i).index; } onPatterChangeLister.onPatterChange(passwordStr); } } }
5、根据图案密码回调进行相应处理。
mLockPatterView.SetOnPatterChangeLister(new LockPatterView.OnPatterChangeLister() { @Override public void onPatterChange(String passwordStr) { if (passwordStr != null) { if(pwdStr.equals("")){//设置密码 if(setPwd.equals("")){//第一次设置密码 setPwd=passwordStr; pwdTv_.setText("请绘制确认密码"); mLockPatterView.resetPoint(); }else{ if(setPwd.equals(passwordStr)){ sharedPreferences.edit().putString("pwd",setPwd).commit(); Toast.makeText(MainActivity.this, "密码设置成功", Toast.LENGTH_LONG).show(); finish(); }else{ setPwd=""; pwdTv_.setText("两次密码绘制不一致,请重新绘制"); mLockPatterView.resetPoint(); } } }else{//验证密码 if(pwdStr.equals(passwordStr)){ Toast.makeText(MainActivity.this, "恭喜你,密码输入正确", Toast.LENGTH_LONG).show(); pwdStr=""; mLockPatterView.resetPoint(); pwdTv_.setText("请先绘制图案密码"); }else{ pwdTv_.setText("密码绘制错误,请重新绘制"); mLockPatterView.resetPoint(); } } } else { pwdTv_.setText("至少5个图案"); } } @Override public void onPatterStart(boolean isStart) { } });
6、最终效果
五、源码下载
0 0
- 基于Android的图案解锁实现
- android图案解锁功能的实现
- [Android UI]android-lockpattern图案解锁的实现分享
- Android中图案解锁的设计原理和实现过程
- Android实现九宫格图案解锁
- Android 图案解锁
- [源码]Android安卓应用手势锁图案解锁的实现
- 安卓中图案解锁的实现原理和实现过程
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- android解决图形解锁图案忘记的方法
- 快给你的app上锁吧(android图案解锁)
- UVA208在一个图中,给定终点和起点,搜索路线,巧妙剪枝
- 航电 acm 2013
- torcs源码分析--(2)关键文件及结构
- HDU 5495 LCS (置换)
- torcs源码分析--(3)总览
- 基于Android的图案解锁实现
- php 基于PDO下的exec()函数查询
- lua脚本的基本语法(二)
- Mount VDI as logical drive on host
- java.lang.NoSuchFieldError: count at org.eclipse.jface.viewers.ColumnViewer$1.mouseDown
- bzoj3714【PA2014】Kuglarz
- 例题5.13 战争和物流 LA4080
- 素描绘画中体积和空间感问题探讨
- 10.4凌晨做题——洛谷P1220关路灯