转载自品略图书馆
本文虽然是一个简单的自定义View,但是考虑的非常周到,处理了很多的细节~
Demo效果图
--方框模式--
--下划线模式--
1
分析
宽高计算
各个长宽、各个变量含义
因为下划线的密码输入框和方框的密码输入框实际上仅有绘制横线还是绘制方框的区别而已,对于坐标的计算以及逻辑都是一样的,所以这里我们就以下划线密码输入框为例子,对比较关键的代码进行一下分析。
2
源码分析
从图片可以看出,整个View的宽高度计算公式为 :
View宽度 = 单个密码框的宽度 * 密码位数 + 密码框间隔 * (密码位数 - 1)
View高度 = 密码框的高度
现在我们已经知道计算公式了,可以开始撸代码了,还是老套路,先继承View重写onMeasure方法,代码如下:
计算完View的宽高之后,我们还需要计算一下密码文本的大小,光标的宽高,这里我们在onSizeChanged中进行计算
现在我们需要的大小都计算好了,可以进行关键的一步,便是绘制,重写onDraw方法,代码如下:
这里因为我们是以下划线为例子,所以我们先看一下绘制下划线的drawUnderLine方法
接下来是绘制密码drawCipherText方法
然后接下来是绘制光标drawCursor方法,代码如下:
现在我们绘制的工作基本完成,但是光标还不会闪动,这里我们用一个定时器Timer让它闪动,具体代码如下:
代码很简单,就是将当前显示状态置反,并且重绘。我们在onAttachedToWindow方法中开启定时器
在onDetachedFromWindow方法中停止定时器
到这里基本上我们的View已经绘制完成并且可以展示,但是我们还缺少密码输入还有键盘的监听事件呢对吧。这里我们只允许密码为数字,重写onCreateInputConnection方法,代码如下:
并且定义一个监听密码输入状态的监听者PasswordListener
实现我们自己的OnKeyListener
这里解释下为什么输入数字的时候需要将keyCode减去7,这里我们可以查看一下KeyEvent的源码
可以发现,数字所对应的keycode与自身数字相差7
我们接着看按下键盘删除键时的方法delete
逻辑很简单,就是记录下删除的字符,然后根据当前所处的下标删除后将其返回。
接下来看一下输入密码时的add方法
逻辑与删除差不多,其中多了一个对是否达到输入位数进行了判断,并回调接口。
最后,别忘记设置View可点击,并且对点击事件进行处理,点击弹出软键盘,否则点击控件是不会弹出软键盘的
点击的时候弹出软键盘,我们可以重写onTouchEvent方法
在失去焦点时隐藏软键盘,重写onWindowFocusChanged方法
重写onSaveInstanceState方法和onRestoreInstanceState对状态进行保存和恢复
到这里基本主要的逻辑就已经ok了