Android实现短信验证码输入框

本文实例为大家分享了Android实现短信验证码输入框的具体代码,供大家参考,具体内容如下

其实用官方自定的那个inputEditText默认带下划线的,然后自己再实行焦点和输入框弹出等操作也可以。

写这个自定义View主要是为了练习。

/**

* 实现了粘贴事件监听回调的 EditText

*/

open class ListenPasteEditTextTest : AppCompatEditText {

constructor(context: Context): super(context)

constructor(context: Context, attributeSet: AttributeSet): super(context,attributeSet)

constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int): super(context, attributeSet, defStyleAttr)

var lisenter: ClipInterface ? = null

override fun onTextContextMenuItem(id: Int): Boolean {

when(id) {

//剪切复制黏贴

android.R.id.cut -> lisenter?.onCut();

android.R.id.copy -> lisenter?.onCopy();

android.R.id.paste -> lisenter?.onPaste();

}

return super.onTextContextMenuItem(id)

}

}

interface ClipInterface{

fun onCut()

fun onCopy()

fun onPaste()

}

/**

* 手机验证码输入控件

*/

class VerificationCodeInputTest(context: Context, attributeSet: AttributeSet) : ViewGroup(context, attributeSet), ClipInterface{

private val box = 4

private val boxWidth = 120

private val boxHeight = 120

private var childPadding = 14

private val TYPE_NUMBER = "number"

private val TYPE_TEXT = "text"

private val TYPE_PASSWORD = "password"

private val TYPE_PHONE = "phone"

private val boxBgFocus: Drawable? = null

private val boxBgNormal: Drawable? = null

private val inputType = TYPE_NUMBER

var listener: VerCideListener? = null

init {

val textWatcher = object : TextWatcher{

override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

}

override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

}

override fun afterTextChanged(s: Editable?) {

if (s != null) {

if (s.isNotEmpty()) {

focus()

checkAndCommit()

}

}

}

}

val onKeyListener = OnKeyListener { v, keyCode, event ->

if (keyCode == KeyEvent.KEYCODE_DEL) {

//backFocus();

backFocusClearAll()

}

false

}

//四个输入框

for (index in 0 until box) {

val editText = ListenPasteEditTextTest(context)

val layoutParams = LinearLayout.LayoutParams(boxWidth, boxHeight)

layoutParams.bottomMargin = childPadding

layoutParams.topMargin = childPadding

layoutParams.leftMargin = childPadding

layoutParams.rightMargin = childPadding

layoutParams.gravity = Gravity.CENTER

editText.layoutParams = layoutParams

editText.lisenter = this

editText.setOnKeyListener(onKeyListener)

//设置背景颜色,就是输入框中的下划线

setBg(editText, false)

editText.setTextColor(Color.BLACK)

editText.gravity = Gravity.CENTER

//最多给你输入一个字符

editText.filters = arrayOf<InputFilter>(InputFilter.LengthFilter(1))

//设置textView输入内容的显示模式

if (TYPE_PASSWORD == inputType) {

editText.transformationMethod = PasswordTransformationMethod.getInstance()

} else if (TYPE_TEXT == inputType) {

editText.inputType = InputType.TYPE_CLASS_TEXT

} else if (TYPE_PHONE == inputType) {

editText.inputType = InputType.TYPE_CLASS_PHONE

}

editText.id = index

//设置字符宽度

editText.setEms(1)

editText.addTextChangedListener(textWatcher)

addView(editText, index)

}

}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

var parentWidth = measuredWidth

//如果在xml中配置的是match_patent 则直接获取当前手机的width尺寸

if (parentWidth == ViewGroup.LayoutParams.MATCH_PARENT) {

parentWidth = getScreenWidth()

}

Log.d(javaClass.name, "onMeasure width $parentWidth")

val count = childCount

for (i in 0 until count) {

val child = getChildAt(i)

this.measureChild(child, widthMeasureSpec, heightMeasureSpec)

}

if (count > 0) {

val child = getChildAt(0)

val cWidth = child.measuredWidth

if (parentWidth != ViewGroup.LayoutParams.WRAP_CONTENT) {

// 重新计算padding

childPadding = (parentWidth - cWidth * count) / (count + 1)

}

val cHeight = child.measuredHeight

val maxH = cHeight + 2 * childPadding

val maxW = cWidth * count + childPadding * (count + 1)

//上面都是计算当前editText的width加上pandding,之后设置给父布局

setMeasuredDimension(

View.resolveSize(maxW, widthMeasureSpec),

View.resolveSize(maxH, heightMeasureSpec)

)

}

}

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {

val childCount = childCount

for (i in 0 until childCount) {

val child = getChildAt(i)

child.visibility = View.VISIBLE

val cWidth = child.measuredWidth

val cHeight = child.measuredHeight

val cl = childPadding + i * (cWidth + childPadding)

val cr = cl + cWidth

val ct = childPadding

val cb = ct + cHeight

child.layout(cl, ct, cr, cb)

}

}

private fun getScreenWidth(): Int {

val resources = this.resources

val dm = resources.displayMetrics

return dm.widthPixels

}

override fun onCut() {

}

override fun onCopy() {

}

override fun onPaste() {

val copyText = getCutAndCopyText()

// 如果是数字并且 length 和 填写位数一致才会进行填充

if (isNumeric(copyText) && copyText.length == box) {

for (i in 0 until childCount) {

(getChildAt(i) as EditText).append(copyText.get(i).toString())

}

}

}

fun setBg(editText: EditText, focus: Boolean) {

if (boxBgNormal != null && !focus) {

editText.background = boxBgNormal

} else if (boxBgFocus != null && focus) {

editText.background = boxBgFocus

}

}

private fun focus() {

val count = childCount

var editText: EditText

for (i in 0 until count) {

editText = getChildAt(i) as EditText

if (editText.text.isEmpty()) {

editText.requestFocus()

return

}

}

}

private fun checkAndCommit() {

val stringBuilder = StringBuilder()

var full = false

for (i in 0 until box) {

val editText = getChildAt(i) as EditText

val content = editText.text.toString()

if (!content.isEmpty()) {

stringBuilder.append(content)

}

}

if (stringBuilder.length == box) {

full = true

}

if (full) {

if (listener != null) {

listener?.onComplete(stringBuilder.toString())

backFocusClearAll()

}

}

}

//清空所有并重新输入

fun backFocusClearAll() {

var editText: EditText

for (i in 0 until box) {

editText = getChildAt(i) as EditText

editText.setText("")

editText.clearFocus()

}

getChildAt(0).requestFocus()

}

/**

* 判断是否是数字

*

* @param str

* @return

*/

private fun isNumeric(str: String?): Boolean {

if (str == null || str.isEmpty()) {

return false

}

for (i in 0 until str.length) {

if (!Character.isDigit(str[i])) {

return false

}

}

return true

}

/**

* 获取剪贴板内容

*/

private fun getCutAndCopyText(): String {

val manager = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager

if (manager != null && manager.hasPrimaryClip() && manager.primaryClip!!.itemCount > 0) {

val addedText = manager.primaryClip!!.getItemAt(0).text

if (addedText != null) {

return addedText.toString()

}

}

return ""

}

}

interface VerCideListener {

fun onComplete(content: String)

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 Android实现短信验证码输入框 的全部内容, 来源链接: utcz.com/p/244122.html

回到顶部