前言
在平常使用手机的过程中,九宫格解锁是我们经常接触到的。常见的比如有锁屏中的九宫格,还有支付宝中的九宫格等。因为九宫格可以保护用户的隐私,所以它的应用面很广泛。那么今天我们就来自定义一个属于自己的九宫格吧!
首先我们来分析一下实现九宫格解锁的思路:当用户的手指触摸到某一个点时,先判断该点是否在九宫格的某一格范围之内,若在范围内,则该格变成选中的状态;之后用户手指滑动的时候,以该格的圆心为中心,用户手指为终点,两点连线。最后当用户手指抬起时,判断划过的九宫格密码是否和原先的密码匹配。
大致的思路流程就是上面这样的了,下面我们可以来实践一下。
Point 类
我们先来创建一个 Point
类,用来表示九宫格锁的九个格子。除了坐标 x
,y
之外,还有三种模式:正常模式、按下模式和错误模式。根据模式不同该格子的颜色会有所不同,这会在下面中说明。
1 | public class Point { |
RotateDegrees类
有了上面的 Point
类之后,我们还要创建一个 RotateDegrees
类,主要作用是计算两个 Point
坐标之间的角度:
1 | public class RotateDegrees { |
ScreenLockView 类
然后我们要先准备好关于九宫格的几张图片,比如在九宫格的格子中,NORMAL_MODE
模式下是蓝色的,被手指按住时九宫格的格子是绿色的,也就是对应着上面 Point 类的中 PRESSED_MODE
模式,还有 ERROR_MODE
模式下是红色的。另外还有圆点之间的连线,也是根据模式不同颜色也会不同。在这里我就不把图片贴出来了,想要的童鞋可以下载源码从中获取。
有了图片资源之后,我们要做的就是先在构造器中加载图片:
1 | public class ScreenLockView extends View { |
在构造器中我们主要就是把图片加载完成,并且得到了格子的半径,即图片宽度的一半。
之后我们来看看 onMeasure(int widthMeasureSpec, int heightMeasureSpec)
方法:
1 | @Override |
在 onMeasure(int widthMeasureSpec, int heightMeasureSpec)
方法中,主要得到对应的偏移量,以便在下面的 onDraw(Canvas canvas)
把九宫格绘制在屏幕中央。
下面就是 onDraw(Canvas canvas)
方法:
1 | @Override |
首先判断了是否为第一次调用 onDraw(Canvas canvas)
方法,若为第一次则对 points 进行初始化:
1 | // 初始化点 |
在 initPoint()
方法中主要创建了九个格子,并设置了相应的位置和密码。初始化完成之后把 init 置为 false ,下次不会再调用。
回过头再看看 onDraw(Canvas canvas)
中其他的逻辑,接下来调用了 drawPoint(canvas)
来绘制格子:
1 | // 画九宫格的格子 |
在绘制格子还是很简单的,主要分为了三种:普通模式下的格子、按下模式下的格子以及错误模式下的格子。
onTouchEvent
在绘制好了格子之后,我们先不看最后的 drawLine(canvas)
方法,因为绘制直线是和用户手指的触摸事件息息相关的,所以我们先把目光转向 onTouchEvent(MotionEvent event)
方法:
1 | @Override |
在 MotionEvent.ACTION_DOWN
中,先在 isPoint(float x, float y)
方法内判断了用户触摸事件的坐标点是否在九宫格的任意一格之内。如果是,则需要把该九宫格的格子添加到 pressedPoint
中:
1 | // 该触摸点是否为格子 |
接下来就是要看 MotionEvent.ACTION_MOVE
的逻辑了。一开始判断了用户触摸的点是否为九宫格的某个格子。但是比 MotionEvent.ACTION_DOWN
还多了一个步骤:若用户触摸了某个格子,还要判断该格子是否已经被包含在 pressedPoint
里面了。
1 | // 是否该格子已经被包含在pressedPoint里面了 |
最后来看看 MotionEvent.ACTION_UP
,把 pressedPoint
里保存的格子遍历后得到用户划出的密码,再和预先设置的密码比较,若相同则回调 OnScreenLockListener
监听器;不相同则把 pressedPoint
中的所有格子的模式设置为错误模式,并在 runnable
中调用 reset()
清空 pressedPoint
,重绘视图,再回调监听器。
1 | private Runnable runnable = new Runnable() { |
现在我们回过头来看看之前在 onDraw(Canvas canvas)
里面的 drawLine(Canvas canvas)
方法:
1 | // 画直线 |
drawLine(Canvas canvas)
整体的逻辑并不复杂,首先将 pressedPoint
中的所有格子依次遍历,将它们连线。之后若是用户的手指还有滑动的话,把最后一个格子和用户手指触摸的点连线。
文末
ScreenLockView
中的代码差不多就是这些了,既然讲解完了那就一起来看看效果吧:
效果还算不错吧,当然你也可以自己设置喜欢的九宫格图片,只要替换一下就可以了。如果对本篇文章有问题,可以留言。
老规矩,附上源码下载链接:
Goodbye ~~