【Android】九宫格手势锁简单实现


现在好多应用都可以设置手势锁,Android本身也有提供手势图案锁屏。作为android菜鸟的我,也忍不住想自己动手实现一下。

下面是应用效果图:



思路:

1.自定义一个View,重写onDraw方法,利用canvas绘制图形。

2.实现onTouch事件

* Down Move Down  每次判断是否有在手指的位置相应处理。

3.直接在布局文件里面 引用View就可以了。

注意:

1.我在实现的过程中遇到一个问题,导致应用奔溃,日志信息也看不懂。最后是在stackoverflow上找到解决方法的。自定义的View一定要实现 两个参数的构造函数(即 SudokuView(Context context, AttributeSet attrs) )

2.onTouchEvent 方法的返回值一定要是 true,不然就无法相应 Move 和Up 事件了【只会鸟Down~】


下面直接上代码

Cell 类(存储圆点的信息)

[java]  view plain  copy
 print ?
  1. package com.example.mummyding.sudokulock;  
  2.   
  3. /** 
  4.  * Created by mummyding on 15-7-17. 
  5.  */  
  6. public class Cell {  
  7.     private int x;  
  8.     private int y;  
  9.     private boolean isSelected;  
  10.   
  11.     public boolean isSelected() {  
  12.         return isSelected;  
  13.     }  
  14.   
  15.     public void setIsSelected(boolean isSelected) {  
  16.         this.isSelected = isSelected;  
  17.     }  
  18.   
  19.     public int getX() {  
  20.         return x;  
  21.     }  
  22.   
  23.     public void setX(int x) {  
  24.         this.x = x;  
  25.     }  
  26.   
  27.     public int getY() {  
  28.         return y;  
  29.     }  
  30.   
  31.     public void setY(int y) {  
  32.         this.y = y;  
  33.     }  
  34. }  

自定义View

[java]  view plain  copy
 print ?
  1. package com.example.mummyding.sudokulock;  
  2.   
  3. import android.app.Notification;  
  4. import android.content.Context;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Color;  
  7. import android.graphics.Paint;  
  8. import android.util.AttributeSet;  
  9. import android.util.DisplayMetrics;  
  10. import android.util.Log;  
  11. import android.view.MotionEvent;  
  12. import android.view.View;  
  13. import android.view.WindowManager;  
  14. import android.widget.Toast;  
  15.   
  16. import java.lang.reflect.Type;  
  17.   
  18. /** 
  19.  * Created by mummyding on 15-7-17. 
  20.  */  
  21. public class SudokuView extends View {  
  22.   
  23.     private static final int COUNT = 3;  
  24.     Cell [] cell;  
  25.     int [] selectedCell;  
  26.     int RADIUS ,OFFSET;  
  27.     int ScreenWidth,ScreenHeight;  
  28.     int startX,startY,selectedCount,lastX,lastY;  
  29.     boolean drawFinish ;  
  30.   
  31.     Paint mPaint ;  
  32.   
  33.   
  34.     public SudokuView(Context context, AttributeSet attrs) {  
  35.         super(context, attrs);  
  36.        init(context);  
  37.   
  38.     }  
  39.   
  40.     private void initCell(){  
  41.         //初始化各点  
  42.         for(int i = 0 ; i < COUNT ; i++ )  
  43.             for (int j = 0 ; j < COUNT ; j++) {  
  44.                 cell[i * COUNT + j].setIsSelected(false);  
  45.                 cell[i * COUNT + j].setX(startX + OFFSET * j - RADIUS/2);  
  46.                 cell[i * COUNT + j].setY(startY + OFFSET * i - RADIUS/2);  
  47.             }  
  48.     }  
  49.     private void init(Context context){  
  50.   
  51.         cell = new Cell[COUNT * COUNT];  
  52.         selectedCell = new int[COUNT*COUNT];  
  53.         mPaint = new Paint();  
  54.         //获取屏幕的宽度和高度  
  55.         WindowManager manager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);  
  56.         DisplayMetrics dm=new DisplayMetrics();  
  57.         manager.getDefaultDisplay().getMetrics(dm);  
  58.   
  59.         ScreenWidth = dm.widthPixels;  
  60.         ScreenHeight = dm.heightPixels;  
  61.   
  62.   
  63.         this.setMinimumWidth(ScreenWidth);  
  64.         this.setMinimumHeight(ScreenHeight);  
  65.   
  66.         drawFinish = false//是否绘制完成  
  67.         selectedCount = 0//已经选中的点个数  
  68.         RADIUS = ScreenWidth / 12//半径  
  69.         OFFSET = ScreenWidth / 4 ; //点之间的间距  
  70.         startX = OFFSET; //起始点横坐标  
  71.         startY = (ScreenHeight - OFFSET * 2) / 2//起始点纵坐标  
  72.   
  73.         for(int i = 0 ; i < COUNT*COUNT ; i++){  
  74.             cell[i] = new Cell();  
  75.         }  
  76.         initCell();  
  77.     }  
  78.   
  79.     int inWhichCircle(int x, int y){  
  80.         for(int i = 0 ; i < COUNT*COUNT ; i++){  
  81.             if(cell[i].isSelected() == false){  
  82.                 if((Math.abs(x - cell[i].getX())<RADIUS) && Math.abs(y - cell[i].getY()) < RADIUS){  
  83.                     return i;  
  84.                 }  
  85.             }  
  86.         }  
  87.         return -1;  
  88.     }  
  89.   
  90.     void drawCell(Canvas canvas){  
  91.        for(int i = 0 ; i < COUNT*COUNT ; i++){  
  92.             //选择画笔&&画圆  
  93.             if(cell[i].isSelected()){  
  94.                 mPaint.setColor(Color.GREEN);  
  95.                 mPaint.setStrokeWidth(10);  
  96.                 //画圆  
  97.                 canvas.drawCircle(cell[i].getX(),cell[i].getY(),RADIUS,mPaint);  
  98.                 mPaint.setStrokeWidth(20);  
  99.                 //画点  
  100.                 canvas.drawPoint(cell[i].getX(),cell[i].getY(),mPaint);  
  101.             } else {  
  102.                 mPaint.setColor(Color.WHITE);  
  103.                 mPaint.setStrokeWidth(5);  
  104.                 //画圆  
  105.                 canvas.drawCircle(cell[i].getX(),cell[i].getY(),RADIUS,mPaint);  
  106.                 //画点  
  107.                 canvas.drawPoint(cell[i].getX(),cell[i].getY(),mPaint);  
  108.             }  
  109.   
  110.         }  
  111.     }  
  112.   
  113.     void drawLine(Canvas canvas) {  
  114.         mPaint.setColor(Color.GREEN);  
  115.         mPaint.setStrokeWidth(5);  
  116.         for(int i = 1 ; i < selectedCount ; i++){  
  117.             Cell lastCell = cell[selectedCell[i-1]],thisCell = cell[selectedCell[i]];  
  118.             canvas.drawLine(lastCell.getX(), lastCell.getY(), thisCell.getX(), thisCell.getY(), mPaint);  
  119.         }  
  120.         if(selectedCount !=0 &&(lastX !=0 || lastY != 0)){  
  121.             canvas.drawLine(cell[selectedCell[selectedCount - 1]].getX(), cell[selectedCell[selectedCount - 1]].getY(), lastX, lastY, mPaint);  
  122.         }  
  123.     }  
  124.   
  125.     @Override  
  126.     protected void onDraw(Canvas canvas) {  
  127.         super.onDraw(canvas);  
  128.         mPaint = new Paint();  
  129.         mPaint.setStrokeWidth(5);;  
  130.         mPaint.setAntiAlias(true);  
  131.         mPaint.setColor(Color.GRAY);  
  132.         mPaint.setStyle(Paint.Style.FILL);  
  133.         mPaint.setStyle(Paint.Style.STROKE);  
  134.         drawCell(canvas);  
  135.         drawLine(canvas);  
  136.     }  
  137.   
  138.   
  139.   
  140.     @Override  
  141.     public boolean onTouchEvent(MotionEvent event) {  
  142.         int tmpIndex;  
  143.         switch (event.getAction()){  
  144.             case MotionEvent.ACTION_DOWN:  
  145.                 drawFinish = false;  
  146.                 if((tmpIndex = inWhichCircle((int)event.getX(),(int)event.getY())) != -1){  
  147.                     cell[tmpIndex].setIsSelected(true);  
  148.                     selectedCell[selectedCount++] = tmpIndex;  
  149.                     this.postInvalidate();  
  150.                 }  
  151.                 break;  
  152.             case MotionEvent.ACTION_MOVE:  
  153.                   if(drawFinish == false){  
  154.                     if((tmpIndex = inWhichCircle((int)event.getX(),(int)event.getY())) != -1){  
  155.                         cell[tmpIndex].setIsSelected(true);  
  156.                         selectedCell[selectedCount++] = tmpIndex;  
  157.                     }  
  158.                 }  
  159.                 lastX = (int) event.getX();  
  160.                 lastY = (int) event.getY();  
  161.                 this.postInvalidate();  
  162.                 break;  
  163.             case MotionEvent.ACTION_UP:  
  164.   
  165.                 drawFinish = true;  
  166.                 lastX = lastY = 0;  
  167.                 selectedCount = 0;  
  168.                 initCell();  
  169.                 this.postInvalidate();  
  170.                 break;  
  171.   
  172.         }  
  173.         return true;  
  174.     }  
  175. }  

布局布局[XML]

[java]  view plain  copy
 print ?
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"  
  3.     android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"  
  4.     android:background="@color/material_blue_grey_800"  
  5.     android:paddingRight="@dimen/activity_horizontal_margin"  
  6.     android:paddingTop="@dimen/activity_vertical_margin"  
  7.     android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">  
  8.   
  9.     <com.example.mummyding.sudokulock.SudokuView  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content"  
  12.         />  
  13. </RelativeLayout>  


完整代码 : https://github.com/MummyDing/SudokuLock


【转载请注明出处】

Author: MummyDing

出处:http://blog.csdn.net/mummyding/article/details/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值