android自定义view之九宫格解锁
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,将点设置成图像。
@Overrideprotected 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) { //九宫格连接数应大于等于5StringBuilder 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);}}
作者:邱钟浩:原文地址
android自定义view之九宫格解锁相关推荐
- Android自定义View,九宫格解锁
/ 今日科技快讯 / 近日微软中国在其官方微博宣布,未来一年内将继续扩大在华招聘,员工总数预计突破1万人.在扩大招聘的基础上,微软还计划在未来三到五年内,对位于北京.上海及苏州的园区进行升级扩 ...
- 自定义View学习——九宫格解锁(LockPatternView)
虽然现在的应用很少在使用九宫格解锁,不过系统的应用锁还是可以见到的.实现的效果如下: 分析 首先需要绘制出九宫格,每一个单元格有两个半径不同的同心圆. 当我们的手指在九宫格上触摸时,如果我们触摸在某个 ...
- android自定义View: 九宫格解锁
本系列自定义View全部采用kt 系统:mac android studio: 4.1.3 kotlin version1.5.0 gradle: gradle-6.5-bin.zip 废话不多说,先 ...
- android 自定义view: 蛛网/雷达图(三)
本系列自定义View全部采用kt 系统mac android studio: 4.1.3 kotlin version1.5.0 gradle: gradle-6.5-bin.zip 本篇效果: 蛛网 ...
- 自定义View之--九宫格图形密码锁
前言: 很多金融和几大商业银行的APP,都使用了九宫格图形密码锁来增强资金账户的安全.我也是金融公司的一员,在空余的时候,写下这个view,可以说是明智之举. 效果预览 这样一个逻辑差不多可以满足基本 ...
- Android技术分享| 【Android 自定义View】多人视频通话控件
[Android 自定义View]多人视频通话控件 *以上图片截自微信等待中界面 等待中界面 上图是微信多人视频通话时未接通的界面状态,可见每个人的 View 中大致需包含了以下元素. 头像 昵称 L ...
- Android自定义View —— TypedArray
在上一篇中Android 自定义View Canvas -- Bitmap写到了TypedArray 这个属性 下面也简单的说一下TypedArray的使用 TypedArray 的作用: 用于从该结 ...
- Android 自定义View —— Canvas
上一篇在android 自定义view Paint 里面 说了几种常见的Point 属性 绘制图形的时候下面总有一个canvas ,Canvas 是是画布 上面可以绘制点,线,正方形,圆,等等,需要和 ...
- android自定义view获取控件,android 自定义控件View在Activity中使用findByViewId得到结果为null...
转载:http://blog.csdn.net/xiabing082/article/details/48781489 1. 大家常常自定义view,,然后在xml 中添加该view 组件..如果在 ...
最新文章
- oracle存储过程拼',【求助】关于oracle存储过程'字符串拼接'
- 抽象工厂模式设计模式_创新设计模式:抽象工厂模式
- python浅拷贝的说法_Python中List的复制(直接复制、浅拷贝、深拷贝)
- 服务器与本地文件共享文件夹,云服务器对本地服务器共享文件夹
- react hooks_React Hooks简介
- leetcode 384 打乱数组
- Ubuntu12.04键盘输入法系统无选择项
- ASP.Net的HtmlHelper和UrlHelper
- 鲁班学院java高级架构师_鲁班学院三期java架构师
- TVS管、稳压管、肖特基二极管
- python云计算有哪些岗位_云计算就业前景怎么样,包括哪些岗位,各岗位主要工作是什么?...
- 史上最全股票指标图文详解
- 一图看懂人工智能技术体系
- 可爱猫python_可爱猫微信机器人框架最新版以及使用教程
- 在线暴躁:script /问题
- CAD三维图形转化成二维图形的过程具体的步骤
- 五月集训-14【栈】
- 消防应急照明和疏散指示系统——集中控制型系统的设计与应用
- 数据仓库-你不知道的HSQL?
- 超好用的图片压缩网站