前言
项目里想添加一个九宫格手势锁的控件,在增加便捷性的同时来增加安全性,虽然是重复造轮子,但是本着自我娱乐的精神就手撸了一个简易九宫格手势锁的自定义view控件。
1、Demo 演示
该控件实现的功能比较简单,一个九宫格手势解锁控件,你可以通过控件的几个属性来对控件的 UI 和功能进行控制:
- 九宫格圆圈的颜色和宽度 (
mLockCircleStrokeColor
/mLockCircleStrokeWidth
) - 手势路径上小圆点的颜色 (
mLockPointStrokeColor
) - 手势路径的颜色以及路径的宽 (
mLockPathStrokeColor
/mLockPathStrokeWidth
) - 定义锁的最小和最大长度 (
mMinLockLength
/mMaxLockLength
) - 锁是否可重复(手势划过的圆圈是否可重复)(
mRepeatAllowed
) - 是否显示锁(手势划过的)路径 (
mShowPath
) - 解(绘制)锁成功或失败时的小圆点和路径的颜色 (
mSuccessColor
/mErrorColor
)
下面是简单演示的动图:
2、实现流程
自定义手势锁控件点实现类直接继承了 View 类,实现上分为了三大块,首先自定义 attr、复写 onDraw(Canvas canvas) 实现界面点绘制、在 onTouchEvent(MotionEvent event) 中处理事件。
2.1、定义 attr
首先,定义下九宫格手势锁控件的相关属性,大概就下面几个,参照之前的说明,很容易理解。
|
|
2.2、界面绘制
OK,进入正题。首先读取相关的属性,这个比较简单,跳过,主要说一下,就是默认的参数情况是:
- 最小最长锁长度是4
- 不允许重复锁
- 不显示手势路径
- 九宫格圆圈宽度是4px
- 手势路径宽度是4px
- 解(绘制)锁成功颜色是蓝色,失败则是红色
- 其他情况颜色均为黑色
那么首先,我们要读取自定义view的长宽数值,然后来初始化我们的画笔了,主要就是四个画笔,一个来绘制九宫格圆圈的 mLockCirclePaint
,并且需要一个 mLockInnerCirclePaint
来配合绘制空心圆圈,mLockPointPaint
负责绘制手势路径上的小圆点,mLockPathPaint
则负责绘制手势路径。
|
|
这里,简单了定义几个绘制的状态,分为四个,看名字也非常容易理解,即初始阶段、解(绘制)锁中、成功和失败。通过状态值来改变相关画笔的颜色值。
|
|
第一步,绘制九宫格空心圆圈,首先根据自定义 View 的宽度来计算空心圆圈的半径 mCirclrRadius,然后找左上角第一个空心圆圈距离自定义 View 的 marginLeft 和 marginTop 值,然后计算下空心圆圈之间的距离 marginBetweenCircles。 接下来,定位左上角第一个空心圆圈的圆点位置 (mStartCx, mStartCy),很好理解吧,marginLeft 和 marginTop 分别加上半径。根据左上角的圆圈的圆心为相对坐标点 (cx, cy),分别找个 9 个空心圆圈的圆心位置并绘制。
|
|
第二步,在绘制完九宫格之后,我们来绘制手势划过九宫格空心圆圈时的小圆点和手势路径。这里所有可能经过的格子的圆心点都已经有了,我们可以很轻松的完成这一步骤。路径显示控制条件为 mShowPath
,绘制的点 mLockList
为记录的手势划过的格子序列(我们这里是 9 个格子,就用了 0-8 来表示)。需要注意的是,在对 mLockList
循环的过程中,路径线段需要两个点,我们从 i=1 开始。先画路径,然后画小圆点,没有在一个循环中同时绘制路径和小圆点,这是因为这样小圆点会完全覆盖路径线段。
|
|
2.3、事件处理
OK,完成了绘制代码之后,要进行事件处理了。首先,为了方便使用,我们定义了一个回调点接口,来方便对解(绘制)锁成功/失败之后进行自己的处理。主要就两个方法:
- 成功回调 onNext,并返回锁(格子)路径序列,方便你去做处理,比如解锁或者存储;
- 失败回调 onError,除了返回锁路径,还返回 errCode:1 为锁过长、2 为锁过短、3 为锁重复
|
|
事件的处理,大致的处理思路是,对于每一次解(绘制)锁来说,当该过程没有结束(解锁时成功或失败视为结束状态)。判断每个 event 是否在某一个九宫格上,根据此条件进行如下处理过程:
- 如果是在其中一个九宫格上,分为三种情况: 1)按下事件,则纪录锁并刷新界面;2)移动事件,判断是否超过最大长度(若超过,则回调接口并刷新界面)、根据是否允许锁重复进行处理,无异常情况则纪录锁并刷新界面;3)抬起事件,重复锁的情况只会在移动过程中出现,这里不用再处理,只处理锁的长度是否在规定的最大和最小长度之间即可;
- 不在的情况,只处理当手指离开 view 的情况,判断解锁是否成功或失败,调用接口方法并刷新界面
相关的代码如下:
|
|
此外,还提供一个方法来重置所有的状态,代码较为简单,如下:
|
|
3、View 使用
该自定义控件已经上传到 GitHub
,你可以 down 下来源码自己改造(项目地址 GestureLockView),也可以直接通过下面的两步加到你的工程中去。
第一步,在你的项目的 build.gradle
中加上 jitpack
:
|
|
第二步,在你需要的 Module
的依赖中加入这个:
|
|
OK, sync 下一你的项目,就可以使用了,那么今天这个简单的九宫格手势锁自定义 View 就到这里了。