Android實(shí)現(xiàn)短信驗(yàn)證碼輸入框
本文實(shí)例為大家分享了Android實(shí)現(xiàn)短信驗(yàn)證碼輸入框的具體代碼,供大家參考,具體內(nèi)容如下
其實(shí)用官方自定的那個(gè)inputEditText默認(rèn)帶下劃線的,然后自己再實(shí)行焦點(diǎn)和輸入框彈出等操作也可以。
寫這個(gè)自定義View主要是為了練習(xí)。
/** * 實(shí)現(xiàn)了粘貼事件監(jiān)聽回調(diào)的 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) { //剪切復(fù)制黏貼 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() }
/** * 手機(jī)驗(yàn)證碼輸入控件 */ 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 } //四個(gè)輸入框 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) //設(shè)置背景顏色,就是輸入框中的下劃線 setBg(editText, false) editText.setTextColor(Color.BLACK) editText.gravity = Gravity.CENTER //最多給你輸入一個(gè)字符 editText.filters = arrayOf<InputFilter>(InputFilter.LengthFilter(1)) //設(shè)置textView輸入內(nèi)容的顯示模式 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 //設(shè)置字符寬度 editText.setEms(1) editText.addTextChangedListener(textWatcher) addView(editText, index) } } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { var parentWidth = measuredWidth //如果在xml中配置的是match_patent 則直接獲取當(dāng)前手機(jī)的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) { // 重新計(jì)算padding childPadding = (parentWidth - cWidth * count) / (count + 1) } val cHeight = child.measuredHeight val maxH = cHeight + 2 * childPadding val maxW = cWidth * count + childPadding * (count + 1) //上面都是計(jì)算當(dāng)前editText的width加上pandding,之后設(shè)置給父布局 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() // 如果是數(shù)字并且 length 和 填寫位數(shù)一致才會(huì)進(jìn)行填充 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() } /** * 判斷是否是數(shù)字 * * @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 } /** * 獲取剪貼板內(nèi)容 */ 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) }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android中3種全屏方法及3種去掉標(biāo)題欄的方法
這篇文章主要介紹了Android中3種全屏方法及3種去掉標(biāo)題欄的方法,二個(gè)問(wèn)題各給出了3種解決方法,并給出實(shí)例代碼,需要的朋友可以參考下2015-06-06Android實(shí)現(xiàn)語(yǔ)音識(shí)別代碼
語(yǔ)音識(shí)別在android上使用起來(lái)很方便也很簡(jiǎn)單.但是有個(gè)前提條件,就是android機(jī)器上必須預(yù)先安裝google的語(yǔ)音搜索工具,今天我們就來(lái)詳細(xì)探討下2015-06-06Android實(shí)現(xiàn)簡(jiǎn)易的計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡(jiǎn)易的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10Android EasyBarrage實(shí)現(xiàn)輕量級(jí)彈幕效果
本篇文章主要介紹了Android EasyBarrage實(shí)現(xiàn)輕量級(jí)彈幕效果,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08android調(diào)用原生圖片裁剪后圖片尺寸縮放的解決方法
這篇文章主要為大家詳細(xì)介紹了android調(diào)用原生圖片裁剪后圖片尺寸縮放的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03Android入門之TableLayout應(yīng)用解析(一)
這篇文章主要介紹了Android入門之TableLayout應(yīng)用,需要的朋友可以參考下2014-08-08Android開發(fā)Jetpack組件WorkManager用例詳解
這篇文章主要為大家介紹了Android開發(fā)Jetpack組件WorkManager的使用案例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02Pagerslidingtabstrip菜單標(biāo)題欄制作方法
這篇文章主要為大家詳細(xì)介紹了Pagerslidingtabstrip菜單標(biāo)題欄的制作方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Android鬧鈴服務(wù)AlarmManager用法深入分析
這篇文章主要介紹了Android鬧鈴服務(wù)AlarmManager用法,結(jié)合實(shí)例形式深入分析了鬧鈴服務(wù)AlarmManager的功能、原理、定義與使用方法,需要的朋友可以參考下2016-08-08