天天看點

android 九宮格手勢密碼 純代碼實作

這幾天項目中要加九宮格手勢密碼,在網上搜了大量資料,大部分都是以圖檔實作為主,集合部分代碼,實作純代碼九宮格。

好了,不廢話了,先上圖。

android 九宮格手勢密碼 純代碼實作
android 九宮格手勢密碼 純代碼實作

效果大概就是這樣,邏輯自己實作,我隻上這個自定義控件的代碼。

1.    point.Java    點的位置

[java]  view plain  copy

  1. public class Point {  
  2.     public static int STATE_NORMAL = 0;  
  3.     public static int STATE_CHECK = 1; //  
  4.     public static int STATE_CHECK_ERROR = 2; //  
  5.     public float x;  
  6.     public float y;  
  7.     public int state = 0;  
  8.     public int index = 0;//  
  9.     public Point() {  
  10.     }  
  11.     public Point(float x, float y, int value) {  
  12.         this.x = x;  
  13.         this.y = y;  
  14.         index = value;  
  15.     }  
  16.     public int getColNum() {  
  17.         return (index - 1) % 3;  
  18.     }  
  19.     public int getRowNum() {  
  20.         return (index - 1) / 3;  
  21.     }  
  22. }  

2.     MathUtil.java   計算兩點之間的距離

[java]  view plain  copy

  1. public class MathUtil {  
  2.     public static double distance(double x1, double y1, double x2, double y2) {  
  3.         return Math.sqrt(Math.abs(x1 - x2) * Math.abs(x1 - x2)  
  4.                 + Math.abs(y1 - y2) * Math.abs(y1 - y2));  
  5.     }  
  6.     public static double pointTotoDegrees(double x, double y) {  
  7.         return Math.toDegrees(Math.atan2(x, y));  
  8.     }  
  9.     public static boolean checkInRound(float sx, float sy, float r, float x,  
  10.             float y) {  
  11.         return Math.sqrt((sx - x) * (sx - x) + (sy - y) * (sy - y)) < r;  
  12.     }  
  13. }  

3.       LocusPassWordView.java   九宮格自定義控件

[java]  view plain  copy

  1. import android.content.Context;  
  2. import android.graphics.Canvas;  
  3. import android.graphics.Paint;  
  4. import android.graphics.Paint.Style;  
  5. import android.graphics.Path;  
  6. import android.util.AttributeSet;  
  7. import android.util.Log;  
  8. import android.view.MotionEvent;  
  9. import android.view.View;  
  10. import android.widget.Toast;  
  11. import com.example.esop.util.MathUtil;  
  12. import com.example.esop.util.Point;  
  13. import java.util.ArrayList;  
  14. import java.util.List;  
  15. import java.util.Timer;  
  16. import java.util.TimerTask;  
  17. public class LocusPassWordView extends View {  
  18.     private float width = 0;  
  19.     private float height = 0;  
  20.     //  
  21.     private boolean isCache = false;  
  22.     //  
  23.     private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  24.     //  
  25.     private Point[][] mPoints = new Point[3][3];  
  26.     //  
  27.     private float dotRadius = 0;  
  28.     //  
  29.     private List<Point> sPoints = new ArrayList<Point>();  
  30.     private boolean checking = false;  
  31.     private long CLEAR_TIME = 1000;  
  32.     private int pwdMaxLen = 9;  
  33.     private int pwdMinLen = 4;  
  34.     private boolean isTouch = true;  
  35.     private Paint arrowPaint;  
  36.     private Paint linePaint;  
  37.     private Paint selectedPaint;  
  38.     private Paint errorPaint;  
  39.     private Paint normalPaint;  
  40.     private int errorColor = 0xffea0945;  
  41.     private int selectedColor = 0xff0596f6;  
  42.     private int outterSelectedColor = 0xff8cbad8;  
  43.     private int outterErrorColor = 0xff901032;  
  44.     private int dotColor = 0xffd9d9d9;  
  45.     private int outterDotColor = 0xff929292;  
  46.     public LocusPassWordView(Context context, AttributeSet attrs, int defStyle) {  
  47.         super(context, attrs, defStyle);  
  48.     }  
  49.     public LocusPassWordView(Context context, AttributeSet attrs) {  
  50.         super(context, attrs);  
  51.     }  
  52.     public LocusPassWordView(Context context) {  
  53.         super(context);  
  54.     }  
  55.     @Override  
  56.     public void onDraw(Canvas canvas) {  
  57.         if (!isCache) {  
  58.             initCache();  
  59.         }  
  60.         drawToCanvas(canvas);  
  61.     }  
  62.     private void drawToCanvas(Canvas canvas) {  
  63.         boolean inErrorState = false;  
  64.         for (int i = 0; i < mPoints.length; i++) {  
  65.             for (int j = 0; j < mPoints[i].length; j++) {  
  66.                 Point p = mPoints[i][j];  
  67.                 if (p.state == Point.STATE_CHECK) {  
  68.                     selectedPaint.setColor(outterSelectedColor);    
  69.                     canvas.drawCircle(p.x, p.y, dotRadius, selectedPaint);  
  70.                     selectedPaint.setColor(selectedColor);  
  71.                     canvas.drawCircle(p.x, p.y, dotRadius/4, selectedPaint);  
  72.                 } else if (p.state == Point.STATE_CHECK_ERROR) {  
  73.                     inErrorState = true;  
  74.                     errorPaint.setColor(outterErrorColor);  
  75.                     canvas.drawCircle(p.x, p.y, dotRadius, errorPaint);  
  76.                     errorPaint.setColor(errorColor);  
  77.                     canvas.drawCircle(p.x, p.y, dotRadius/4, errorPaint);  
  78.                 } else {  
  79.                     normalPaint.setColor(dotColor);  
  80.                     canvas.drawCircle(p.x, p.y, dotRadius, normalPaint);  
  81.                     normalPaint.setColor(outterDotColor);  
  82.                     canvas.drawCircle(p.x, p.y, dotRadius/4, normalPaint);  
  83.                 }  
  84.             }  
  85.         }  
  86.         if (inErrorState) {  
  87.             arrowPaint.setColor(errorColor);  
  88.             linePaint.setColor(errorColor);  
  89.         } else {  
  90.             arrowPaint.setColor(selectedColor);  
  91.             linePaint.setColor(selectedColor);  
  92.         }  
  93.         if (sPoints.size() > 0) {  
  94.             int tmpAlpha = mPaint.getAlpha();  
  95.             Point tp = sPoints.get(0);  
  96.             for (int i = 1; i < sPoints.size(); i++) {  
  97.                 Point p = sPoints.get(i);  
  98.                 drawLine(tp, p, canvas, linePaint);  
  99.                 drawArrow(canvas, arrowPaint, tp, p, dotRadius/4, 38);  
  100.                 tp = p;  
  101.             }  
  102.             if (this.movingNoPoint) {  
  103.                 drawLine(tp, new Point(moveingX, moveingY, -1), canvas, linePaint);  
  104.             }  
  105.             mPaint.setAlpha(tmpAlpha);  
  106.         }  
  107.     }  
  108.     private void drawLine(Point start, Point end, Canvas canvas, Paint paint) {  
  109.         double d = MathUtil.distance(start.x, start.y, end.x, end.y);  
  110.         float rx = (float) ((end.x-start.x) * dotRadius / 4 / d);  
  111.         float ry = (float) ((end.y-start.y) * dotRadius / 4 / d);  
  112.         canvas.drawLine(start.x+rx, start.y+ry, end.x-rx, end.y-ry, paint);  
  113.     }  
  114.     private void drawArrow(Canvas canvas, Paint paint, Point start, Point end, float arrowHeight, int angle) {  
  115.         double d = MathUtil.distance(start.x, start.y, end.x, end.y);  
  116.         float sin_B = (float) ((end.x - start.x) / d);  
  117.         float cos_B = (float) ((end.y - start.y) / d);  
  118.         float tan_A = (float) Math.tan(Math.toRadians(angle));  
  119.         float h = (float) (d - arrowHeight - dotRadius * 1.1);  
  120.         float l = arrowHeight * tan_A;  
  121.         float a = l * sin_B;  
  122.         float b = l * cos_B;  
  123.         float x0 = h * sin_B;  
  124.         float y0 = h * cos_B;  
  125.         float x1 = start.x + (h + arrowHeight) * sin_B;  
  126.         float y1 = start.y + (h + arrowHeight) * cos_B;  
  127.         float x2 = start.x + x0 - b;  
  128.         float y2 = start.y + y0 + a;  
  129.         float x3 = start.x + x0 + b;  
  130.         float y3 = start.y + y0 - a;  
  131.         Path path = new Path();  
  132.         path.moveTo(x1, y1);  
  133.         path.lineTo(x2, y2);  
  134.         path.lineTo(x3, y3);  
  135.         path.close();  
  136.         canvas.drawPath(path, paint);  
  137.     }  
  138.     private void initCache() {  
  139.         width = this.getWidth();  
  140.         height = this.getHeight();  
  141.         float x = 0;  
  142.         float y = 0;  
  143.         if (width > height) {  
  144.             x = (width - height) / 2;  
  145.             width = height;  
  146.         } else {  
  147.             y = (height - width) / 2;  
  148.             height = width;  
  149.         }  
  150.         int leftPadding = 15;  
  151.         float dotPadding = width / 3 - leftPadding;  
  152.         float middleX = width / 2;  
  153.         float middleY = height / 2;  
  154.         mPoints[0][0] = new Point(x + middleX - dotPadding, y + middleY - dotPadding, 1);  
  155.         mPoints[0][1] = new Point(x + middleX, y + middleY - dotPadding, 2);  
  156.         mPoints[0][2] = new Point(x + middleX + dotPadding, y + middleY - dotPadding, 3);  
  157.         mPoints[1][0] = new Point(x + middleX - dotPadding, y + middleY, 4);  
  158.         mPoints[1][1] = new Point(x + middleX, y + middleY, 5);  
  159.         mPoints[1][2] = new Point(x + middleX + dotPadding, y + middleY, 6);  
  160.         mPoints[2][0] = new Point(x + middleX - dotPadding, y + middleY + dotPadding, 7);  
  161.         mPoints[2][1] = new Point(x + middleX, y + middleY + dotPadding, 8);  
  162.         mPoints[2][2] = new Point(x + middleX + dotPadding, y + middleY + dotPadding, 9);  
  163.         Log.d("jerome", "canvas width:"+width);  
  164.         dotRadius = width / 10;  
  165.         isCache = true;  
  166.         initPaints();  
  167.     }  
  168.     private void initPaints() {  
  169.         arrowPaint = new Paint();  
  170.         arrowPaint.setColor(selectedColor);  
  171.         arrowPaint.setStyle(Style.FILL);  
  172.         arrowPaint.setAntiAlias(true);  
  173.         linePaint = new Paint();  
  174.         linePaint.setColor(selectedColor);  
  175.         linePaint.setStyle(Style.STROKE);  
  176.         linePaint.setAntiAlias(true);  
  177.         linePaint.setStrokeWidth(dotRadius / 9);  
  178.         selectedPaint = new Paint();   
  179.         selectedPaint.setStyle(Style.STROKE);  
  180.         selectedPaint.setAntiAlias(true);   
  181.         selectedPaint.setStrokeWidth(dotRadius / 6);  
  182.         errorPaint = new Paint();  
  183.         errorPaint.setStyle(Style.STROKE);  
  184.         errorPaint.setAntiAlias(true);   
  185.         errorPaint.setStrokeWidth(dotRadius / 6);  
  186.         normalPaint = new Paint();  
  187.         normalPaint.setStyle(Style.STROKE);  
  188.         normalPaint.setAntiAlias(true);   
  189.         normalPaint.setStrokeWidth(dotRadius / 9);    
  190.     }  
  191.     public int[] getArrayIndex(int index) {  
  192.         int[] ai = new int[2];  
  193.         ai[0] = index / 3;  
  194.         ai[1] = index % 3;  
  195.         return ai;  
  196.     }  
  197.     private Point checkSelectPoint(float x, float y) {  
  198.         for (int i = 0; i < mPoints.length; i++) {  
  199.             for (int j = 0; j < mPoints[i].length; j++) {  
  200.                 Point p = mPoints[i][j];  
  201.                 if (MathUtil.checkInRound(p.x, p.y, dotRadius, (int) x, (int) y)) {  
  202.                     return p;  
  203.                 }  
  204.             }  
  205.         }  
  206.         return null;  
  207.     }  
  208.     private void reset() {  
  209.         for (Point p : sPoints) {  
  210.             p.state = Point.STATE_NORMAL;  
  211.         }  
  212.         sPoints.clear();  
  213.         this.enableTouch();  
  214.     }  
  215.     private int crossPoint(Point p) {  
  216.         // reset  
  217.         if (sPoints.contains(p)) {  
  218.             if (sPoints.size() > 2) {  
  219.                 //  
  220.                 if (sPoints.get(sPoints.size() - 1).index != p.index) {  
  221.                     return 2;  
  222.                 }  
  223.             }  
  224.             return 1; //  
  225.         } else {  
  226.             return 0; //  
  227.         }  
  228.     }  
  229.     private void addPoint(Point point) {  
  230.         if (sPoints.size() > 0) {  
  231.             Point lastPoint = sPoints.get(sPoints.size() - 1);  
  232.             int dx = Math.abs(lastPoint.getColNum() - point.getColNum());  
  233.             int dy = Math.abs(lastPoint.getRowNum() - point.getRowNum());  
  234.             if ((dx > 1 || dy > 1) && (dx == 0 || dy == 0 || dx == dy)) {  
  235. //          if ((dx > 1 || dy > 1) && (dx != 2 * dy) && (dy != 2 * dx)) {  
  236.                 int middleIndex = (point.index + lastPoint.index) / 2 - 1;  
  237.                 Point middlePoint = mPoints[middleIndex / 3][middleIndex % 3];  
  238.                 if (middlePoint.state != Point.STATE_CHECK) {  
  239.                     middlePoint.state = Point.STATE_CHECK;  
  240.                     sPoints.add(middlePoint);  
  241.                 }  
  242.             }  
  243.         }  
  244.         this.sPoints.add(point);  
  245.     }  
  246.     private String toPointString() {  
  247.         if (sPoints.size() >= pwdMinLen && sPoints.size() <= pwdMaxLen) {  
  248.             StringBuffer sf = new StringBuffer();  
  249.             for (Point p : sPoints) {  
  250.                 sf.append(p.index);  
  251.             }  
  252.             return sf.toString();  
  253.         } else {  
  254.             return "";  
  255.         }  
  256.     }  
  257.     boolean movingNoPoint = false;  
  258.     float moveingX, moveingY;  
  259.     @Override  
  260.     public boolean onTouchEvent(MotionEvent event) {  
  261.         //  
  262.         if (!isTouch) {  
  263.             return false;  
  264.         }  
  265.         movingNoPoint = false;  
  266.         float ex = event.getX();  
  267.         float ey = event.getY();  
  268.         boolean isFinish = false;  
  269.         boolean redraw = false;  
  270.         Point p = null;  
  271.         switch (event.getAction()) {  
  272.         case MotionEvent.ACTION_DOWN: //  
  273.             //  
  274.             if (task != null) {  
  275.                 task.cancel();  
  276.                 task = null;  
  277.                 Log.d("task", "touch cancel()");  
  278.             }  
  279.             //  
  280.             reset();  
  281.             p = checkSelectPoint(ex, ey);  
  282.             if (p != null) {  
  283.                 checking = true;  
  284.             }  
  285.             break;  
  286.         case MotionEvent.ACTION_MOVE:  
  287.             if (checking) {  
  288.                 p = checkSelectPoint(ex, ey);  
  289.                 if (p == null) {  
  290.                     movingNoPoint = true;  
  291.                     moveingX = ex;  
  292.                     moveingY = ey;  
  293.                 }  
  294.             }  
  295.             break;  
  296.         case MotionEvent.ACTION_UP:  
  297.             p = checkSelectPoint(ex, ey);  
  298.             checking = false;  
  299.             isFinish = true;  
  300.             break;  
  301.         }  
  302.         if (!isFinish && checking && p != null) {  
  303.             int rk = crossPoint(p);  
  304.             if (rk == 2) //  
  305.             {  
  306.                 // reset();  
  307.                 // checking = false;  
  308.                 movingNoPoint = true;  
  309.                 moveingX = ex;  
  310.                 moveingY = ey;  
  311.                 redraw = true;  
  312.             } else if (rk == 0) //  
  313.             {  
  314.                 p.state = Point.STATE_CHECK;  
  315.                 addPoint(p);  
  316.                 redraw = true;  
  317.             }  
  318.             // rk == 1  
  319.         }  
  320.         //  
  321.         if (redraw) {  
  322.         }  
  323.         if (isFinish) {  
  324.             if (this.sPoints.size() == 1) {  
  325.                 this.reset();  
  326.             } else if (sPoints.size() < pwdMinLen || sPoints.size() > pwdMaxLen) {  
  327.                 // mCompleteListener.onPasswordTooMin(sPoints.size());  
  328.                 error();  
  329.                 clearPassword();  
  330.                 Toast.makeText(this.getContext(), "手勢密碼少于4個點", Toast.LENGTH_SHORT).show();  
  331.             } else if (mCompleteListener != null) {  
  332.                 this.disableTouch();  
  333.                 mCompleteListener.onComplete(toPointString());  
  334.             }  
  335.         }  
  336.         this.postInvalidate();  
  337.         return true;  
  338.     }  
  339.     private void error() {  
  340.         for (Point p : sPoints) {  
  341.             p.state = Point.STATE_CHECK_ERROR;  
  342.         }  
  343.     }  
  344.     public void markError() {  
  345.         markError(CLEAR_TIME);  
  346.     }  
  347.     public void markError(final long time) {  
  348.         for (Point p : sPoints) {  
  349.             p.state = Point.STATE_CHECK_ERROR;  
  350.         }  
  351.         this.clearPassword(time);  
  352.     }  
  353.     public void enableTouch() {  
  354.         isTouch = true;  
  355.     }  
  356.     public void disableTouch() {  
  357.         isTouch = false;  
  358.     }  
  359.     private Timer timer = new Timer();  
  360.     private TimerTask task = null;  
  361.     public void clearPassword() {  
  362.         clearPassword(CLEAR_TIME);  
  363.     }  
  364.     public void clearPassword(final long time) {  
  365.         if (time > 1) {  
  366.             if (task != null) {  
  367.                 task.cancel();  
  368.                 Log.d("task", "clearPassword cancel()");  
  369.             }  
  370.             postInvalidate();  
  371.             task = new TimerTask() {  
  372.                 public void run() {  
  373.                     reset();  
  374.                     postInvalidate();  
  375.                 }  
  376.             };  
  377.             Log.d("task", "clearPassword schedule(" + time + ")");  
  378.             timer.schedule(task, time);  
  379.         } else {  
  380.             reset();  
  381.             postInvalidate();  
  382.         }  
  383.     }  
  384.     //  
  385.     private OnCompleteListener mCompleteListener;  
  386.     public void setOnCompleteListener(OnCompleteListener mCompleteListener) {  
  387.         this.mCompleteListener = mCompleteListener;  
  388.     }  
  389.     public interface OnCompleteListener {  
  390.         public void onComplete(String password);  
  391.     }  
  392. }  

大概代碼就是上面三個類了,儲存九宮格密碼 有很多種,我使用 SharedPreferences 儲存,相信都知道。

下面附上這三個類的源碼下載下傳位址:

     http://download.csdn.net/detail/daiwei714/8409191