Android實現(xiàn)短信驗證碼輸入框
更新時間:2021年11月23日 07:44:07 作者:放開那只肥雞
這篇文章主要為大家詳細介紹了Android實現(xiàn)短信驗證碼輸入框,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
本文實例為大家分享了Android實現(xiàn)短信驗證碼輸入框的具體代碼,供大家參考,具體內容如下

其實用官方自定的那個inputEditText默認帶下劃線的,然后自己再實行焦點和輸入框彈出等操作也可以。
寫這個自定義View主要是為了練習。
/**
* 實現(xiàn)了粘貼事件監(jiān)聽回調的 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()
// 如果是數(shù)字并且 length 和 填寫位數(shù)一致才會進行填充
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
}
/**
* 獲取剪貼板內容
*/
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中TabLayout結合ViewPager實現(xiàn)頁面切換
這篇文章主要為大家詳細介紹了Android中TabLayout結合ViewPager實現(xiàn)頁面切換效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12

