android自定义view之九宫格解锁
来源:互联网 发布:java第三方服务器ftp 编辑:程序博客网 时间:2024/03/29 02:48
android自定义view之九宫格解锁
更多细节请看源码
https://github.com/que123567/lockview
1. 定义一个类作为九宫格的格子
包含坐标和索引(用来记录密码)
point含三种状态分别对应三种不同情况下点的图片样式
package lockview;/** * Created by smaug on 2017/5/11. */public class Point { public float x; public float y; private int index; public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public static final int STATU_NORNAL = 0; public static final int STATU_PRESSED = 1; public static final int STATU_ERROR = 2; public int state; public void setState(int state) { this.state = state; } public int getState() { return state; } public Point() {super();} public Point(float x, float y) { this.x = x; this.y = y; } public float getX() { return x; } public void setX(float x) { this.x = x; } public float getY() { return y; } public void setY(float y) { this.y = y; }}
- 2.新建类LockView继承自View
重写onDraw()方法- 初始化点的时候根据获取当前屏幕的宽高,比对来确定当前状态是横屏还是竖屏
- 从资源中获取Bitmap,将点设置成图像。
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); initPoints(); initPaint(); } private void drawPoints(Canvas canvas) { for (int i = 0; i < points.length; i++) { for (int j = 0; j < points[i].length; j++) { Point point = points[i][j]; if (point.getState() == Point.STATU_NORNAL) { //获取当前点的坐标,减去图片的半径得到left和top的坐标点 canvas.drawBitmap(point_normal, point.x - br, point.y - br, null); } else if (point.getState() == Point.STATU_PRESSED) { canvas.drawBitmap(point_pressed, point.x - br, point.y - br, null); } else if (point.getState() == Point.STATU_ERROR) { canvas.drawBitmap(point_error, point.x - br, point.y - br, null); } } } }public class LockView extends View { private void initPoints() { width = getWidth(); height = getHeight(); if (height > width) {//竖屏 offsetY = (height - width) / 2; height = width; } else { //横屏 offsetX = (height - width) / 2; width = height; } /** * 定义9个点的坐标 */ points = new Point[row][colun]; int index = 1; for (int i = 0; i < row; i++) { for (int j = 0; j < colun; j++) { points[i][j] = new Point(offsetX + (width / (row + 1)) * (i + 1), offsetY + (width / (colun + 1)) * (j + 1)); points[i][j].setIndex(index); index++; } } /** * 从资源中获取Bitmap */ point_normal = BitmapFactory.decodeResource(getResources(), R.drawable.point_normal); point_pressed = BitmapFactory.decodeResource(getResources(), R.drawable.point_pressed); point_error = BitmapFactory.decodeResource(getResources(), R.drawable.point_error); br = point_normal.getWidth() / 2; }}
显示结果如下图
- 3.重写onTouchEvent
case MotionEvent.ACTION_DOWN: reset();//先清空之前绘制的状态 checkedPoint = checkPoint(eventX, eventY, br); if (checkedPoint != null) { isSelecte = true; checkedPoint.setState(Point.STATU_PRESSED); } break;
checkPoint()通过计算坐标距离判断当前手指坐标是否在point图片上
private Point checkPoint(float eventX, float eventY, float br) { for (int i = 0; i < points.length; i++) { for (int j = 0; j < points[i].length; j++) { Point point = points[i][j]; double distance = getDistance(point.x, point.y, eventX, eventY); if (distance < br) { return point; } } } return null; }
getDistance()利用勾股定理计算坐标距离
private double getDistance(float x, float y, float eventX, float eventY) { return Math.sqrt(Math.abs(x - eventX) * Math.abs(x - eventX) + Math.abs(y - eventY) * Math.abs(y - eventY)); }
这个时候手指接触都某个点,某个点的状态就会从normal转换为pressed,其对应的图片也会改变。
4.添加点与点之间的连线
LockView中定义一个Point类的List —>pointList 记录用户按下的点当pointList为空,即用户未按下任一点的时候不绘制线段,其余时刻都绘制
绘制线段调用canvas的drawLine()方法,传入起始点x,y坐标与目标点x,y坐标与一个自定义的paint画笔绘制线段
private void drawLine(Canvas canvas) { if (pointList.size() > 0) { Point a = pointList.get(0); for (int i = 1; i < pointList.size(); i++) { Point b = pointList.get(i); canvas.drawLine(a.x, a.y, b.x, b.y, paint); a = b; } if (!moveOnPoint) { // canvas.drawLine(a.x, a.y, eventX, eventY, paint); } } }
效果如图所示
- 5.自动连接中间点
在九宫格中,如果用户跳开中间点只连接了头尾两个点,按照规则应该把中间点自动连上。
即在ACTION_MOVE过程中始终判断中间点是否被连入,而中间点的判断方式为首尾点坐标/2.
case MotionEvent.ACTION_MOVE: if (isSelecte) { checkedPoint = checkPoint(eventX, eventY, br); if (checkedPoint != null) { if (!pointList.contains(checkedPoint)) { middlePoint = checkPoint((checkedPoint.x + lastPoint.x) / 2, (checkedPoint.y + lastPoint.y) / 2, br); if (middlePoint != null) { middlePoint.setState(Point.STATU_PRESSED); } } checkedPoint.setState(Point.STATU_PRESSED); moveOnPoint = true; } else { moveOnPoint = false; } } break;
6.此外,在绘制过程中会记录密码,在使用该LockView时可设置setOnLockSuccessed监听来判断,其中带有参数:正确密码-passward
对应的,连接数少于5判定为连接失败,也有对应的监听事件。
if (pointList != null) { if (pointList.size() == 1) { reset();//重置 } else if (pointList.size() < 5) {//个数不足 errorPoint();//绘制错误的图案 if (onLockChangeListener != null) { //失败 onLockChangeListener.setOnLockError(); } } else if (pointList.size() >= 5) { //九宫格连接数应大于等于5 StringBuilder passward = new StringBuilder(); for (int i = 0; i < pointList.size(); i++) { int tmpIndex = pointList.get(i).getIndex(); passward.append(tmpIndex + ""); } if (onLockChangeListener != null)//成功 onLockChangeListener.setOnLockSuccessed(passward); } }
阅读全文
0 0
- android自定义view之九宫格解锁
- android自定义view之九宫格解锁
- 自定义view之九宫格手势解锁空间
- 自定义View----Android九宫格手势密码解锁
- android 自定义view实现九宫格手势解锁
- 自定义View----Android九宫格手势密码解锁
- Android进阶之自定义View实战(二)九宫格手势解锁实现
- Android 自定义九宫格解锁
- Android自定义控件之滑动解锁九宫格
- android简单的九宫格解锁view
- 自定义view学习-创建自己的九宫格解锁view
- 【Android】自定义控件实现九宫格解锁
- Android自定义九宫格图案解锁
- Android自定义控件实现九宫格解锁
- 九点(九宫格)式手势解锁自定义view
- 九点(九宫格)式手势解锁自定义view
- Android之九宫格解锁的实现
- Android之九宫格解锁的实现
- MySQL数据库分区(Database partition)
- org.hibernate.InstantiationException: No default constructor for entity
- 剑指offer_连续子数组的最大和
- 查看多媒体文件速度优化升级
- 我的世界 粘液块科技 配方计算 配方表
- android自定义view之九宫格解锁
- 查询另一张表中某字符出现次数 sql
- C++经典书籍
- wamp环境下,PHP中安装redis
- kafka produce源码研究
- 经典卷积神经网络模型
- java基础知识之抽象类
- Windows下MyEclipse安装及破解
- Android Studio AVD 遇到的问题