热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

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

这篇文章主要为大家详细介绍了纯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)) 

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 sPoints = new ArrayList(); 
 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  0) { 
   int tmpAlpha = mPaint.getAlpha(); 
   Point tp = sPoints.get(0); 
   for (int i = 1; i  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  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()  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实现纯代码九宫格

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


推荐阅读
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 【Windows】实现微信双开或多开的方法及步骤详解
    本文介绍了在Windows系统下实现微信双开或多开的方法,通过安装微信电脑版、复制微信程序启动路径、修改文本文件为bat文件等步骤,实现同时登录两个或多个微信的效果。相比于使用虚拟机的方法,本方法更简单易行,适用于任何电脑,并且不会消耗过多系统资源。详细步骤和原理解释请参考本文内容。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
author-avatar
g37112969
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有