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ù)一致才會進(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)
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android中3種全屏方法及3種去掉標(biāo)題欄的方法
這篇文章主要介紹了Android中3種全屏方法及3種去掉標(biāo)題欄的方法,二個(gè)問題各給出了3種解決方法,并給出實(shí)例代碼,需要的朋友可以參考下2015-06-06
Android實(shí)現(xiàn)簡易的計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡易的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10
Android EasyBarrage實(shí)現(xiàn)輕量級彈幕效果
本篇文章主要介紹了Android EasyBarrage實(shí)現(xiàn)輕量級彈幕效果,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
android調(diào)用原生圖片裁剪后圖片尺寸縮放的解決方法
這篇文章主要為大家詳細(xì)介紹了android調(diào)用原生圖片裁剪后圖片尺寸縮放的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
Android入門之TableLayout應(yīng)用解析(一)
這篇文章主要介紹了Android入門之TableLayout應(yīng)用,需要的朋友可以參考下2014-08-08
Android開發(fā)Jetpack組件WorkManager用例詳解
這篇文章主要為大家介紹了Android開發(fā)Jetpack組件WorkManager的使用案例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02
Pagerslidingtabstrip菜單標(biāo)題欄制作方法
這篇文章主要為大家詳細(xì)介紹了Pagerslidingtabstrip菜單標(biāo)題欄的制作方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Android鬧鈴服務(wù)AlarmManager用法深入分析
這篇文章主要介紹了Android鬧鈴服務(wù)AlarmManager用法,結(jié)合實(shí)例形式深入分析了鬧鈴服務(wù)AlarmManager的功能、原理、定義與使用方法,需要的朋友可以參考下2016-08-08

