【Android】九宫格手势锁简单实现
16lz
2021-01-23
现在好多应用都可以设置手势锁,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 类(存储圆点的信息)
package com.example.mummyding.sudokulock;/** * Created by mummyding on 15-7-17. */public class Cell { private int x; private int y; private boolean isSelected; public boolean isSelected() { return isSelected; } public void setIsSelected(boolean isSelected) { this.isSelected = isSelected; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; }}
自定义View
package com.example.mummyding.sudokulock;import android.app.Notification;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.WindowManager;import android.widget.Toast;import java.lang.reflect.Type;/** * Created by mummyding on 15-7-17. */public class SudokuView extends View { private static final int COUNT = 3; Cell [] cell; int [] selectedCell; int RADIUS ,OFFSET; int ScreenWidth,ScreenHeight; int startX,startY,selectedCount,lastX,lastY; boolean drawFinish ; Paint mPaint ; public SudokuView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void initCell(){ //初始化各点 for(int i = 0 ; i < COUNT ; i++ ) for (int j = 0 ; j < COUNT ; j++) { cell[i * COUNT + j].setIsSelected(false); cell[i * COUNT + j].setX(startX + OFFSET * j - RADIUS/2); cell[i * COUNT + j].setY(startY + OFFSET * i - RADIUS/2); } } private void init(Context context){ cell = new Cell[COUNT * COUNT]; selectedCell = new int[COUNT*COUNT]; mPaint = new Paint(); //获取屏幕的宽度和高度 WindowManager manager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics dm=new DisplayMetrics(); manager.getDefaultDisplay().getMetrics(dm); ScreenWidth = dm.widthPixels; ScreenHeight = dm.heightPixels; this.setMinimumWidth(ScreenWidth); this.setMinimumHeight(ScreenHeight); drawFinish = false; //是否绘制完成 selectedCount = 0; //已经选中的点个数 RADIUS = ScreenWidth / 12; //半径 OFFSET = ScreenWidth / 4 ; //点之间的间距 startX = OFFSET; //起始点横坐标 startY = (ScreenHeight - OFFSET * 2) / 2; //起始点纵坐标 for(int i = 0 ; i < COUNT*COUNT ; i++){ cell[i] = new Cell(); } initCell(); } int inWhichCircle(int x, int y){ for(int i = 0 ; i < COUNT*COUNT ; i++){ if(cell[i].isSelected() == false){ if((Math.abs(x - cell[i].getX())<RADIUS) && Math.abs(y - cell[i].getY()) < RADIUS){ return i; } } } return -1; } void drawCell(Canvas canvas){ for(int i = 0 ; i < COUNT*COUNT ; i++){ //选择画笔&&画圆 if(cell[i].isSelected()){ mPaint.setColor(Color.GREEN); mPaint.setStrokeWidth(10); //画圆 canvas.drawCircle(cell[i].getX(),cell[i].getY(),RADIUS,mPaint); mPaint.setStrokeWidth(20); //画点 canvas.drawPoint(cell[i].getX(),cell[i].getY(),mPaint); } else { mPaint.setColor(Color.WHITE); mPaint.setStrokeWidth(5); //画圆 canvas.drawCircle(cell[i].getX(),cell[i].getY(),RADIUS,mPaint); //画点 canvas.drawPoint(cell[i].getX(),cell[i].getY(),mPaint); } } } void drawLine(Canvas canvas) { mPaint.setColor(Color.GREEN); mPaint.setStrokeWidth(5); for(int i = 1 ; i < selectedCount ; i++){ Cell lastCell = cell[selectedCell[i-1]],thisCell = cell[selectedCell[i]]; canvas.drawLine(lastCell.getX(), lastCell.getY(), thisCell.getX(), thisCell.getY(), mPaint); } if(selectedCount !=0 &&(lastX !=0 || lastY != 0)){ canvas.drawLine(cell[selectedCell[selectedCount - 1]].getX(), cell[selectedCell[selectedCount - 1]].getY(), lastX, lastY, mPaint); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint = new Paint(); mPaint.setStrokeWidth(5);; mPaint.setAntiAlias(true); mPaint.setColor(Color.GRAY); mPaint.setStyle(Paint.Style.FILL); mPaint.setStyle(Paint.Style.STROKE); drawCell(canvas); drawLine(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { int tmpIndex; switch (event.getAction()){ case MotionEvent.ACTION_DOWN: drawFinish = false; if((tmpIndex = inWhichCircle((int)event.getX(),(int)event.getY())) != -1){ cell[tmpIndex].setIsSelected(true); selectedCell[selectedCount++] = tmpIndex; this.postInvalidate(); } break; case MotionEvent.ACTION_MOVE: if(drawFinish == false){ if((tmpIndex = inWhichCircle((int)event.getX(),(int)event.getY())) != -1){ cell[tmpIndex].setIsSelected(true); selectedCell[selectedCount++] = tmpIndex; } } lastX = (int) event.getX(); lastY = (int) event.getY(); this.postInvalidate(); break; case MotionEvent.ACTION_UP: drawFinish = true; lastX = lastY = 0; selectedCount = 0; initCell(); this.postInvalidate(); break; } return true; }}
布局布局[XML]
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:background="@color/material_blue_grey_800" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <com.example.mummyding.sudokulock.SudokuView android:layout_width="wrap_content" android:layout_height="wrap_content" /></RelativeLayout>
完整代码 :https://github.com/MummyDing/SudokuLock
【转载请注明出处】
Author: MummyDing
出处:http://blog.csdn.net/mummyding/article/details/
更多相关文章
- Android 基础:常用布局 介绍 & 使用(附 属性查询)
- android:scaleType="matrix"布局文件加载图片时候的显示方式
- Android的XML布局文件中layout_width和width的区别
- Android 开发中 布局加载的原理
- 全屏显示布局随机图片的显示
- Android 自定义布局的Toast