纯android代码实现九宫格手势密码

 更新时间:2018年07月30日 11:14:37   转载 作者:九幽神君  
这篇文章主要为大家详细介绍了纯android代码实现九宫格手势密码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

这几天项目中要加九宫格手势密码,在网上搜了大量资料,大部分都是以图片实现为主,集合部分代码,android实现纯代码九宫格。

好了,不废话了,先上图。

效果大概就是这样,逻辑自己实现,我只上这个自定义控件的代码。

1.    point.Java  点的位置

/** 
 * 点位置 
 */ 
public class Point { 
 public static int STATE_NORMAL = 0; 
 public static int STATE_CHECK = 1; // 
 public static int STATE_CHECK_ERROR = 2; // 
 
 public float x; 
 public float y; 
 public int state = 0; 
 public int index = 0;// 
 
 public Point() { 
 
 } 
 
 public Point(float x, float y, int value) { 
  this.x = x; 
  this.y = y; 
  index = value; 
 } 
  
 public int getColNum() { 
  return (index - 1) % 3; 
 } 
  
 public int getRowNum() { 
  return (index - 1) / 3; 
 } 
 
} 

2.     MathUtil.java   计算两点之间的距离

public class MathUtil { 
 /** 
  * 
  * @param x1 
  * @param y1 
  * @param x2 
  * @param y2 
  * @return 
  */ 
 public static double distance(double x1, double y1, double x2, double y2) { 
  return Math.sqrt(Math.abs(x1 - x2) * Math.abs(x1 - x2) 
    + Math.abs(y1 - y2) * Math.abs(y1 - y2)); 
 } 
 
 /** 
  * 
  * @param x 
  * @param y 
  * @return 
  */ 
 public static double pointTotoDegrees(double x, double y) { 
  return Math.toDegrees(Math.atan2(x, y)); 
 } 
  
 public static boolean checkInRound(float sx, float sy, float r, float x, 
   float y) { 
  return Math.sqrt((sx - x) * (sx - x) + (sy - y) * (sy - y)) < r; 
 } 
} 

3.      LocusPassWordView.java   九宫格自定义控件

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.graphics.Paint.Style; 
import android.graphics.Path; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 
import android.widget.Toast; 
import com.example.esop.util.MathUtil; 
import com.example.esop.util.Point; 
 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Timer; 
import java.util.TimerTask; 
 
public class LocusPassWordView extends View { 
 private float width = 0; 
 private float height = 0; 
 
 // 
 private boolean isCache = false; 
 // 
 private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
 
 // 
 private Point[][] mPoints = new Point[3][3]; 
 // 
 private float dotRadius = 0; 
 // 
 private List<Point> sPoints = new ArrayList<Point>(); 
 private boolean checking = false; 
 private long CLEAR_TIME = 1000; 
 private int pwdMaxLen = 9; 
 private int pwdMinLen = 4; 
 private boolean isTouch = true; 
  
 private Paint arrowPaint; 
 private Paint linePaint; 
 private Paint selectedPaint; 
 private Paint errorPaint; 
 private Paint normalPaint; 
 private int errorColor = 0xffea0945; 
 private int selectedColor = 0xff0596f6; 
 private int outterSelectedColor = 0xff8cbad8; 
 private int outterErrorColor = 0xff901032; 
 private int dotColor = 0xffd9d9d9; 
 private int outterDotColor = 0xff929292; 
 
 public LocusPassWordView(Context context, AttributeSet attrs, int defStyle) { 
  super(context, attrs, defStyle); 
 } 
 
 public LocusPassWordView(Context context, AttributeSet attrs) { 
  super(context, attrs); 
 } 
 
 public LocusPassWordView(Context context) { 
  super(context); 
 } 
 
 @Override 
 public void onDraw(Canvas canvas) { 
  if (!isCache) { 
   initCache(); 
  } 
  drawToCanvas(canvas); 
 } 
 
 private void drawToCanvas(Canvas canvas) { 
  boolean inErrorState = false; 
  for (int i = 0; i < mPoints.length; i++) { 
   for (int j = 0; j < mPoints[i].length; j++) { 
    Point p = mPoints[i][j]; 
    if (p.state == Point.STATE_CHECK) { 
     selectedPaint.setColor(outterSelectedColor); 
     canvas.drawCircle(p.x, p.y, dotRadius, selectedPaint); 
     selectedPaint.setColor(selectedColor); 
     canvas.drawCircle(p.x, p.y, dotRadius/4, selectedPaint); 
    } else if (p.state == Point.STATE_CHECK_ERROR) { 
     inErrorState = true; 
     errorPaint.setColor(outterErrorColor); 
     canvas.drawCircle(p.x, p.y, dotRadius, errorPaint); 
     errorPaint.setColor(errorColor); 
     canvas.drawCircle(p.x, p.y, dotRadius/4, errorPaint); 
    } else { 
     normalPaint.setColor(dotColor); 
     canvas.drawCircle(p.x, p.y, dotRadius, normalPaint); 
     normalPaint.setColor(outterDotColor); 
     canvas.drawCircle(p.x, p.y, dotRadius/4, normalPaint); 
    } 
   } 
  } 
   
  if (inErrorState) { 
   arrowPaint.setColor(errorColor); 
   linePaint.setColor(errorColor); 
  } else { 
   arrowPaint.setColor(selectedColor); 
   linePaint.setColor(selectedColor); 
  } 
 
  if (sPoints.size() > 0) { 
   int tmpAlpha = mPaint.getAlpha(); 
   Point tp = sPoints.get(0); 
   for (int i = 1; i < sPoints.size(); i++) { 
    Point p = sPoints.get(i); 
    drawLine(tp, p, canvas, linePaint); 
    drawArrow(canvas, arrowPaint, tp, p, dotRadius/4, 38); 
    tp = p; 
   } 
   if (this.movingNoPoint) { 
    drawLine(tp, new Point(moveingX, moveingY, -1), canvas, linePaint); 
   } 
   mPaint.setAlpha(tmpAlpha); 
  } 
 
 } 
  
 private void drawLine(Point start, Point end, Canvas canvas, Paint paint) { 
  double d = MathUtil.distance(start.x, start.y, end.x, end.y); 
  float rx = (float) ((end.x-start.x) * dotRadius / 4 / d); 
  float ry = (float) ((end.y-start.y) * dotRadius / 4 / d); 
  canvas.drawLine(start.x+rx, start.y+ry, end.x-rx, end.y-ry, paint); 
 } 
  
 private void drawArrow(Canvas canvas, Paint paint, Point start, Point end, float arrowHeight, int angle) { 
  double d = MathUtil.distance(start.x, start.y, end.x, end.y); 
  float sin_B = (float) ((end.x - start.x) / d); 
  float cos_B = (float) ((end.y - start.y) / d); 
  float tan_A = (float) Math.tan(Math.toRadians(angle)); 
  float h = (float) (d - arrowHeight - dotRadius * 1.1); 
  float l = arrowHeight * tan_A; 
  float a = l * sin_B; 
  float b = l * cos_B; 
  float x0 = h * sin_B; 
  float y0 = h * cos_B; 
  float x1 = start.x + (h + arrowHeight) * sin_B; 
  float y1 = start.y + (h + arrowHeight) * cos_B; 
  float x2 = start.x + x0 - b; 
  float y2 = start.y + y0 + a; 
  float x3 = start.x + x0 + b; 
  float y3 = start.y + y0 - a; 
  Path path = new Path(); 
  path.moveTo(x1, y1); 
  path.lineTo(x2, y2); 
  path.lineTo(x3, y3); 
  path.close(); 
  canvas.drawPath(path, paint); 
 } 
 
 private void initCache() { 
  width = this.getWidth(); 
  height = this.getHeight(); 
  float x = 0; 
  float y = 0; 
 
  if (width > height) { 
   x = (width - height) / 2; 
   width = height; 
  } else { 
   y = (height - width) / 2; 
   height = width; 
  } 
   
  int leftPadding = 15; 
  float dotPadding = width / 3 - leftPadding; 
  float middleX = width / 2; 
  float middleY = height / 2; 
 
  mPoints[0][0] = new Point(x + middleX - dotPadding, y + middleY - dotPadding, 1); 
  mPoints[0][1] = new Point(x + middleX, y + middleY - dotPadding, 2); 
  mPoints[0][2] = new Point(x + middleX + dotPadding, y + middleY - dotPadding, 3); 
  mPoints[1][0] = new Point(x + middleX - dotPadding, y + middleY, 4); 
  mPoints[1][1] = new Point(x + middleX, y + middleY, 5); 
  mPoints[1][2] = new Point(x + middleX + dotPadding, y + middleY, 6); 
  mPoints[2][0] = new Point(x + middleX - dotPadding, y + middleY + dotPadding, 7); 
  mPoints[2][1] = new Point(x + middleX, y + middleY + dotPadding, 8); 
  mPoints[2][2] = new Point(x + middleX + dotPadding, y + middleY + dotPadding, 9); 
   
  Log.d("jerome", "canvas width:"+width); 
  dotRadius = width / 10; 
  isCache = true; 
   
  initPaints(); 
 } 
  
 private void initPaints() { 
  arrowPaint = new Paint(); 
  arrowPaint.setColor(selectedColor); 
  arrowPaint.setStyle(Style.FILL); 
  arrowPaint.setAntiAlias(true); 
   
  linePaint = new Paint(); 
  linePaint.setColor(selectedColor); 
  linePaint.setStyle(Style.STROKE); 
  linePaint.setAntiAlias(true); 
  linePaint.setStrokeWidth(dotRadius / 9); 
   
  selectedPaint = new Paint(); 
  selectedPaint.setStyle(Style.STROKE); 
  selectedPaint.setAntiAlias(true); 
  selectedPaint.setStrokeWidth(dotRadius / 6); 
   
  errorPaint = new Paint(); 
  errorPaint.setStyle(Style.STROKE); 
  errorPaint.setAntiAlias(true); 
  errorPaint.setStrokeWidth(dotRadius / 6); 
   
  normalPaint = new Paint(); 
  normalPaint.setStyle(Style.STROKE); 
  normalPaint.setAntiAlias(true); 
  normalPaint.setStrokeWidth(dotRadius / 9); 
 } 
 
 /** 
  * 
  * 
  * @param index 
  * @return 
  */ 
 public int[] getArrayIndex(int index) { 
  int[] ai = new int[2]; 
  ai[0] = index / 3; 
  ai[1] = index % 3; 
  return ai; 
 } 
 
 /** 
  * @param x 
  * @param y 
  * @return 
  */ 
 private Point checkSelectPoint(float x, float y) { 
  for (int i = 0; i < mPoints.length; i++) { 
   for (int j = 0; j < mPoints[i].length; j++) { 
    Point p = mPoints[i][j]; 
    if (MathUtil.checkInRound(p.x, p.y, dotRadius, (int) x, (int) y)) { 
     return p; 
    } 
   } 
  } 
  return null; 
 } 
 
 /** 
  * 
  */ 
 private void reset() { 
  for (Point p : sPoints) { 
   p.state = Point.STATE_NORMAL; 
  } 
  sPoints.clear(); 
  this.enableTouch(); 
 } 
 
 /** 
  * 
  * 
  * @param p 
  * @return 
  */ 
 private int crossPoint(Point p) { 
  // reset 
  if (sPoints.contains(p)) { 
   if (sPoints.size() > 2) { 
    // 
    if (sPoints.get(sPoints.size() - 1).index != p.index) { 
     return 2; 
    } 
   } 
   return 1; // 
  } else { 
   return 0; // 
  } 
 } 
 
 /** 
  * 
  * 
  * @param point 
  */ 
 private void addPoint(Point point) { 
  if (sPoints.size() > 0) { 
   Point lastPoint = sPoints.get(sPoints.size() - 1); 
   int dx = Math.abs(lastPoint.getColNum() - point.getColNum()); 
   int dy = Math.abs(lastPoint.getRowNum() - point.getRowNum()); 
   if ((dx > 1 || dy > 1) && (dx == 0 || dy == 0 || dx == dy)) { 
//   if ((dx > 1 || dy > 1) && (dx != 2 * dy) && (dy != 2 * dx)) { 
    int middleIndex = (point.index + lastPoint.index) / 2 - 1; 
    Point middlePoint = mPoints[middleIndex / 3][middleIndex % 3]; 
    if (middlePoint.state != Point.STATE_CHECK) { 
     middlePoint.state = Point.STATE_CHECK; 
     sPoints.add(middlePoint); 
    } 
   } 
  } 
  this.sPoints.add(point); 
 } 
 
 /** 
  * @param 
  * @return 
  */ 
 private String toPointString() { 
  if (sPoints.size() >= pwdMinLen && sPoints.size() <= pwdMaxLen) { 
   StringBuffer sf = new StringBuffer(); 
   for (Point p : sPoints) { 
    sf.append(p.index); 
   } 
   return sf.toString(); 
  } else { 
   return ""; 
  } 
 } 
 
 boolean movingNoPoint = false; 
 float moveingX, moveingY; 
 
 @Override 
 public boolean onTouchEvent(MotionEvent event) { 
  // 
  if (!isTouch) { 
   return false; 
  } 
 
  movingNoPoint = false; 
 
  float ex = event.getX(); 
  float ey = event.getY(); 
  boolean isFinish = false; 
  boolean redraw = false; 
  Point p = null; 
  switch (event.getAction()) { 
  case MotionEvent.ACTION_DOWN: // 
   // 
   if (task != null) { 
    task.cancel(); 
    task = null; 
    Log.d("task", "touch cancel()"); 
   } 
   // 
   reset(); 
   p = checkSelectPoint(ex, ey); 
   if (p != null) { 
    checking = true; 
   } 
   break; 
  case MotionEvent.ACTION_MOVE: 
   if (checking) { 
    p = checkSelectPoint(ex, ey); 
    if (p == null) { 
     movingNoPoint = true; 
     moveingX = ex; 
     moveingY = ey; 
    } 
   } 
   break; 
  case MotionEvent.ACTION_UP: 
   p = checkSelectPoint(ex, ey); 
   checking = false; 
   isFinish = true; 
   break; 
  } 
  if (!isFinish && checking && p != null) { 
 
   int rk = crossPoint(p); 
   if (rk == 2) // 
   { 
    // reset(); 
    // checking = false; 
 
    movingNoPoint = true; 
    moveingX = ex; 
    moveingY = ey; 
 
    redraw = true; 
   } else if (rk == 0) // 
   { 
    p.state = Point.STATE_CHECK; 
    addPoint(p); 
    redraw = true; 
   } 
   // rk == 1 
 
  } 
 
  // 
  if (redraw) { 
 
  } 
  if (isFinish) { 
   if (this.sPoints.size() == 1) { 
    this.reset(); 
   } else if (sPoints.size() < pwdMinLen || sPoints.size() > pwdMaxLen) { 
    // mCompleteListener.onPasswordTooMin(sPoints.size()); 
    error(); 
    clearPassword(); 
    Toast.makeText(this.getContext(), "手势密码少于4个点", Toast.LENGTH_SHORT).show(); 
   } else if (mCompleteListener != null) { 
    this.disableTouch(); 
    mCompleteListener.onComplete(toPointString()); 
   } 
  } 
  this.postInvalidate(); 
  return true; 
 } 
 
 /** 
  * 
  */ 
 private void error() { 
  for (Point p : sPoints) { 
   p.state = Point.STATE_CHECK_ERROR; 
  } 
 } 
 
 public void markError() { 
  markError(CLEAR_TIME); 
 } 
 
 public void markError(final long time) { 
  for (Point p : sPoints) { 
   p.state = Point.STATE_CHECK_ERROR; 
  } 
  this.clearPassword(time); 
 } 
 
 public void enableTouch() { 
  isTouch = true; 
 } 
 
 public void disableTouch() { 
  isTouch = false; 
 } 
 
 private Timer timer = new Timer(); 
 private TimerTask task = null; 
 
 
 public void clearPassword() { 
  clearPassword(CLEAR_TIME); 
 } 
 
 public void clearPassword(final long time) { 
  if (time > 1) { 
   if (task != null) { 
    task.cancel(); 
    Log.d("task", "clearPassword cancel()"); 
   } 
   postInvalidate(); 
   task = new TimerTask() { 
    public void run() { 
     reset(); 
     postInvalidate(); 
    } 
   }; 
   Log.d("task", "clearPassword schedule(" + time + ")"); 
   timer.schedule(task, time); 
  } else { 
   reset(); 
   postInvalidate(); 
  } 
 
 } 
 
 // 
 private OnCompleteListener mCompleteListener; 
 
 /** 
  * @param mCompleteListener 
  */ 
 public void setOnCompleteListener(OnCompleteListener mCompleteListener) { 
  this.mCompleteListener = mCompleteListener; 
 } 
 
 public interface OnCompleteListener { 
   
  public void onComplete(String password); 
 } 
} 

大概代码就是上面三个类了,保存九宫格密码 有很多种,我使用 SharedPreferences 保存,相信都知道。

下面附上这三个类的源码下载地址:android实现纯代码九宫格

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

相关文章

  • Android实现环形进度条的实例

    Android实现环形进度条的实例

    本文通过实例代码给大家介绍了android实现环形进度条的实例代码,代码简单易懂,非常不错,需要的朋友参考下
    2017-01-01
  • Android开发实现实时检测蓝牙连接状态的方法【附源码下载】

    Android开发实现实时检测蓝牙连接状态的方法【附源码下载】

    这篇文章主要介绍了Android开发实现实时检测蓝牙连接状态的方法,涉及Android针对蓝牙连接状态的监测操作相关实现技巧,需要的朋友可以参考下
    2017-11-11
  • Android编程实现图片的颜色处理功能示例

    Android编程实现图片的颜色处理功能示例

    这篇文章主要介绍了Android编程实现图片的颜色处理功能,涉及Android拖动条的使用及图形颜色处理相关操作技巧,需要的朋友可以参考下
    2018-02-02
  • Android持久化保存cookie的方法

    Android持久化保存cookie的方法

    这篇文章主要介绍了Android持久化保存cookie的方法,在解析网页信息的时候,需要登录后才能访问,所以使用httpclient模拟登录,然后把cookie保存下来,以供下一次访问使用,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • 快速掌握Android屏幕的知识点

    快速掌握Android屏幕的知识点

    相信不少设计师和工程师都被安卓设备纷繁的屏幕搞得晕头转向,我既做UI设计,也做过一点安卓界面布局,刚好对这块内容比较熟悉,所以在此我将此部分知识重新梳理出来分享给大家!有需要的朋友们可以参考借鉴,下面来一起学习学习吧。
    2016-11-11
  • 自定义View之kotlin绘制折线图实例教程

    自定义View之kotlin绘制折线图实例教程

    折线图是我们在开发中经常会遇到的一个需求,下面这篇文章主要给大家介绍了关于自定义View之kotlin绘制折线图的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-09-09
  • Android卫星菜单效果的实现方法

    Android卫星菜单效果的实现方法

    这篇文章主要介绍了Android卫星菜单效果的实现方法,需要的朋友可以参考下
    2017-05-05
  • Android SharedPreferences实现保存登录数据功能

    Android SharedPreferences实现保存登录数据功能

    这篇文章主要为大家详细介绍了Android SharedPreferences实现保存登录数据功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • Android打包篇:Android Studio将代码打包成jar包教程

    Android打包篇:Android Studio将代码打包成jar包教程

    这篇文章主要介绍了Android打包篇:Android Studio将代码打包成jar包教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • Android学习之AppWidget笔记分享

    Android学习之AppWidget笔记分享

    这篇文章主要为大家详细介绍了Android学习笔记之AppWidget的相关资料,感兴趣的小伙伴们可以参考一下
    2016-08-08

最新评论