华域联盟 Andriod 纯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)) < 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代码实现九宫格手势密码

转载请保留出处和原文链接:https://www.cnhackhy.com/107071.htm

本文来自网络,不代表华域联盟立场,转载请注明出处。

作者: sterben

android实现桌面移动悬浮窗口

Kotlin自定义View系列教程之标尺控件(选择身高、体重等)的实现

发表回复

联系我们

联系我们

2551209778

在线咨询: QQ交谈

邮箱: [email protected]

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们