android图案解锁功能的实现
来源:互联网 发布:苹果电脑软件如何升级 编辑:程序博客网 时间:2024/04/29 21:37
我们经常会在app中看到图案解锁的功能,所以寻思做一个,在某客视频上看到了教程,自己跟着做了一遍,记录一下,顺便理清一下思路。
思路讲解:
首先自定义一个图案的view,其中实现onDraw方法,以及添加接口回调进行验证密码正确性。
自定义view效果如下:
首先新建一个记录点的坐标的一个bean
public class Point { //表示图案状态 public static int STATE_NORMAL=0; public static int STATE_PRESS=1; public static int STATE_ERROR=2; //坐标 float x,y; int state=STATE_NORMAL; public Point(float x, float y) { this.x = x; this.y = y; } //判断按下屏幕的点是否在某一个圆圈的区域内 public float distance(Point a) { float distance= (float) Math.sqrt((x-a.x)*(x-a.x)+(y-a.y)*(y-a.y)); return distance; }}
下面是自定义view代码:
public class GestureLockView extends View { //三张不同状态圆的图片 private Bitmap error,normal,press; // private ArrayList<Point> pointlist=new ArrayList<>(); //设置圆的坐标位置的数组 private Point[][] points=new Point[3][3]; //画圆的画笔(后面的参数为抗锯齿的作用) private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG); //设置回调监听事件 private OnDrawFinsihListner listner; //保存圆的半径 private float radius; public GestureLockView(Context context) { super(context); } public GestureLockView(Context context, AttributeSet attrs) { super(context, attrs); } public GestureLockView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //判断是否初始化 private boolean inited=false; @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //ondraw方法会多次调用所以要设置标记位判断是否调用过 if (!inited){ init(); } //画图 drawPoints(canvas); //画线 if (pointlist.size()>0) { //冲重第一个点画起 Point a=pointlist.get(0); for (int i=1;i<pointlist.size();i++) { Point b=pointlist.get(i); drawLine(canvas,a,b); a=b; } if (isDraw) { drawLine(canvas,a,new Point(mouseX,mouseY)); } } } //绘制圆圈背景图案 private void drawPoints(Canvas canvas){ for (int i=0;i<points.length;i++ ) { for (int j=0;j<points[i].length;j++) { if (points[i][j].state==Point.STATE_NORMAL) { //正常状态 canvas.drawBitmap(normal,points[i][j].x-radius,points[i][j].y-radius,paint); } else if (points[i][j].state==Point.STATE_PRESS) { //按下状态 canvas.drawBitmap(press,points[i][j].x-radius,points[i][j].y-radius,paint); }else { //错误状态 canvas.drawBitmap(error,points[i][j].x-radius,points[i][j].y-radius,paint); } } } } //初始化 private void init(){ pressPaint.setColor(Color.BLUE); //画笔宽度 pressPaint.setStrokeWidth(5); errorPaint.setColor(Color.RED); errorPaint.setStrokeWidth(5); //获取图片 error= BitmapFactory.decodeResource(getResources(),R.drawable.error); press=BitmapFactory.decodeResource(getResources(),R.drawable.press); normal=BitmapFactory.decodeResource(getResources(),R.drawable.normal); radius=error.getHeight()/2; int width=getWidth(); Log.e("width",width+""); int height=getHeight(); Log.e("height",height+""); //显示位置的偏移量 int offset=Math.abs(width-height)/2; //图案偏移量 int offsetX,offsetY; //小方格偏移量 int space; //判断横屏还是竖屏 if (width>height){ offsetX=offset; offsetY=0; space=height/4; } else { space=width/4; offsetX=0; offsetY=offset; } //绘制圆圈 for (int i=0;i<3;i++) { for (int j=0;j<3;j++){ points[i][j]=new Point(offsetX+space*(j+1),offsetY+space*(i+1)); } } inited=true; } //获取触摸的点 private float mouseX,mouseY; //是否在绘制状态 private boolean isDraw=false; //触摸事件 @Override public boolean onTouchEvent(MotionEvent event) { //得到按下坐标 mouseX=event.getX(); mouseY=event.getY(); int[] ij; int i,j; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //清空绘制过程 resetPoint(); ij=getSelectionPoint(); if (ij!=null) { isDraw=true; i=ij[0]; j=ij[1]; points[i][j].state=Point.STATE_PRESS; pointlist.add(points[i][j]); passlist.add(i*3+j); } break; case MotionEvent.ACTION_MOVE: if (isDraw) { ij=getSelectionPoint(); if (ij!=null) { i=ij[0]; j=ij[1]; if (!pointlist.contains(points[i][j])) { points[i][j].state=Point.STATE_PRESS; pointlist.add(points[i][j]); passlist.add(i*3+j); } } } break; case MotionEvent.ACTION_UP: boolean valid=false; if (listner!=null&&isDraw) { valid=listner.OnDrawFinished(passlist); } if (!valid) { for (Point point:pointlist) point.state=Point.STATE_ERROR; } isDraw=false; break; } this.postInvalidate(); return true; } //当手指按下,判断属于那个圆圈 private int[] getSelectionPoint() { Point pMouse=new Point(mouseX,mouseY); for (int i=0;i<points.length;i++){ for (int j=0;j<points[i].length;j++) { if (points[i][j].distance(pMouse)<radius) { int[] result=new int[2]; result[0]=i; result[1]=j; return result; } } } return null; } private Paint errorPaint=new Paint(); private Paint pressPaint=new Paint(); private void drawLine(Canvas canvas,Point a,Point b) { if (a.state==Point.STATE_PRESS) { canvas.drawLine(a.x,a.y,b.x,b.y,pressPaint); } else if (a.state==Point.STATE_ERROR){ canvas.drawLine(a.x,a.y,b.x,b.y,errorPaint); } } public void resetPoint(){ pointlist.clear(); passlist.clear(); for (int i=0;i<points.length;i++) { for (int k=0;k<points[i].length;k++) points[i][k].state=Point.STATE_NORMAL; } this.postInvalidate(); } private ArrayList<Integer> passlist=new ArrayList<>(); public interface OnDrawFinsihListner { boolean OnDrawFinished(List<Integer> passlist); } public void setOnDrawFinishedListener(OnDrawFinsihListner listener) { this.listner=listener; }}
主页面布局:
<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:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="设置图案密码" android:id="@+id/button" android:layout_gravity="center_horizontal" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试图案密码" android:id="@+id/button2" android:layout_gravity="center_horizontal" /></LinearLayout>
主页面代码:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, SettingAct.class); startActivity(intent); } }); findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(MainActivity.this,LockAct.class); startActivity(intent); } }); }}
设置页面代码:
public class SettingAct extends AppCompatActivity { private GestureLockView lockView; private List<Integer> passlist; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_setting); lockView= (GestureLockView) findViewById(R.id.view); findViewById(R.id.btn_reset).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { lockView.resetPoint(); } }); findViewById(R.id.btn_save).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (passlist!=null) { StringBuilder sb=new StringBuilder(); for (Integer i:passlist) { sb.append(i); } SharedPreferences sharedPreferences=SettingAct.this.getSharedPreferences("password", Context.MODE_PRIVATE); SharedPreferences.Editor editor=sharedPreferences.edit(); editor.putString("password", sb.toString()); editor.commit(); Toast.makeText(SettingAct.this,"保存完成",Toast.LENGTH_SHORT).show(); Intent intent=new Intent(SettingAct.this,MainActivity.class); startActivity(intent); } } }); lockView.setOnDrawFinishedListener(new GestureLockView.OnDrawFinsihListner() { @Override public boolean OnDrawFinished(List<Integer> passlist) { if (passlist.size()<3) { Toast.makeText(SettingAct.this,"密码不能小于三个点",Toast.LENGTH_SHORT).show(); return false; }else { SettingAct.this.passlist=passlist; return true; } } }); }}
测试页面代码:
public class LockAct extends AppCompatActivity {private String passwaord; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_lock); GestureLockView gestureLockView= (GestureLockView) findViewById(R.id.view2); SharedPreferences sharedPreferences=getSharedPreferences("password", Context.MODE_PRIVATE); passwaord =sharedPreferences.getString("password",""); Log.e("password",passwaord); gestureLockView.setOnDrawFinishedListener(new GestureLockView.OnDrawFinsihListner() { @Override public boolean OnDrawFinished(List<Integer> passlist) { StringBuilder stringBuilder=new StringBuilder(); for (Integer i:passlist) { stringBuilder.append(i); } Log.e("sb",stringBuilder.toString()); if (stringBuilder.toString().equals(passwaord)) { Toast.makeText(LockAct.this, "密码正确", Toast.LENGTH_SHORT).show(); return true; } else { Toast.makeText(LockAct.this, "密码错误", Toast.LENGTH_SHORT).show(); return false; } } }); }}
最终效果图:
注意:
这里很奇怪,为什么布局显示正常的图案,但是在模拟器中圆圈就变大了,然后我发现换为API 15的页面布局中显示出来的就是当前的结果,如果哪位大大知道为什么请告诉我好么!!!!!!!
0 0
- android图案解锁功能的实现
- 基于Android的图案解锁实现
- [Android UI]android-lockpattern图案解锁的实现分享
- [Unity3D]使用GL实现图案解锁功能
- Android中图案解锁的设计原理和实现过程
- Android实现九宫格图案解锁
- Android 图案解锁
- [源码]Android安卓应用手势锁图案解锁的实现
- 安卓中图案解锁的实现原理和实现过程
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- Android屏幕解锁图案破解
- android解决图形解锁图案忘记的方法
- [尺取法] poj3061 Subsequence
- 阿里云windows2008运维笔记
- 南邮 OJ 1026 五位以内的对称素数
- oracle 时间类型date 按天模糊查询
- C语言深度解剖——读书笔记-8、指针和数组
- android图案解锁功能的实现
- Android App 启动过程分析
- 信号量解决进程的同步和互斥
- CodeForces-496B Secret Combination
- 高斯消元模板(+解异或方程组)
- C专家编程读书笔记一:C语言晦涩难懂的声明
- 消息机制工作原理(isa指针)
- Java(Android)线程池-初级理解与应用
- 越南CTF的crypto 100