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)
}

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

(0)

相关推荐

  • Android自定义控件实现通用验证码输入框(二)

    本文实例为大家分享了Android实现通用验证码输入框第2篇具体实现代码,供大家参考,具体内容如下 效果图 话不多说,我们还是先上效果图,可以先先看看是不是自己想要的 闲聊 这种验证码输入框使用组合控件就比较烦人了,所以这边直接使用自定View步奏实现 源码 自定义输入框属性(attrs.xml) <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable

  • Android自定义控件通用验证码输入框的实现

    需求 4位验证码输入框: 效果图: 1. 输入框一行可输入4位数字类型的验证码: 2. 4位数字之间有间隔(包括底线): 3. 输入框不允许有光标: 4. 底线根据输入位置显示高亮(蓝色): 6. 输入完成,回调结果,输入过程中,也进行回调: 分析 这种效果,很难直接在Edittext上处理: -- 输入框均分4等份,还要有间隔: -- 更难处理的是Edittext输入框禁止光标,那么,没有光标,我们如何调起虚拟键盘输入数据? -- 等... 与其在一个控件上折腾,这么难受,不如自定义一个控件,

  • Android实现常见的验证码输入框实例代码

    前言 验证码输入框是很多APP必不可少的组件,之前在重构注册登录页面的时候,重新设计了UI,所以不能再简单的用EditText来做了,所以这篇文章将分享一下如何实现一个常见的验证码输入框.下面话不多说了,来一起看看详细的介绍吧. 正文 先搂一眼效果吧 不要把注意力都放在头顶的那一抹绿上,重点在输入框,可能大多数APP里都是采用6个方框的UI效果,我这里是按照我们设计的要求,用6根横线来划出6个数字的位置.一开始我想的是直接用6个TextView,然后传递焦点的做法,但是发现实现起来有一定的难度.

  • Android 自定义验证码输入框的实例代码(支持粘贴连续性)

    需求 1.能自定义输入框个数和样式 2.支持长按粘贴或剪切板内容自动填充(粘贴连续性) 其中第2点是最为重要的,正是其他人没有这点,逼得自己弄一个 示例 别人的示例: 粘贴居然不支持连续性,只能粘贴第一个字符,所以用的有点难受 自己的示例: 原理 大致是Edittext + n* TextView,然后设置edittext字体跟背景颜色都为透明,隐藏光标 Edittext:监听edittext每次输入一个字符就赋值到对应的TextView上,然后在清空自己 下划线:在TextView下面添加Vi

  • Android自定义View验证码输入框

    本文实例为大家分享了Android自定义View验证码输入框的具体代码,供大家参考,具体内容如下 验证码输入框 1.先看下样式 2.直接上代码 public class MyVcode extends AppCompatEditText { private int mFigures = 0;// 验证码个数 private int mCodeMargin = 0;// 验证码之间的间距 private int mSelectColor = 0;// 选中框的颜色 private int mNor

  • Android View教程之自定义验证码输入框效果

    前言 首先,我们来看看实现的是怎么样的效果: 如果我们拿到这样的UI,想到的布局应该是用4个EditText包在横向的LinearLayout里面,但今天要讲的View,所以我们决定用一个自定义的EditText 画出来. 学到什么? 基本理解画布概念 画布的状态.平移 布局测量 画图片 功能需求 高亮当前输入框 输入满4个数字自动调用方法 思路 完全重画一个EditText,就包含了测量布局和重新绘制这两个关键步骤.好了,到这里理一下整体的思路: 根据验证码个数以及边框大小来计算输入框显示的宽

  • Android实现自定义验证码输入框效果(实例代码)

    这里提一下,这个当时也是在网上看到一个博主写的代码改了下用在我么项目中的验证码输入框.博主的地址不记得了这里只能顺带标注一下... 效果图如下: 就是这个酱紫 直入主题,代码如下: xml布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" androi

  • Android自定义控件实现通用验证码输入框

    本文为大家分享了Android实现通用验证码输入框的具体代码,供大家参考,具体内容如下 效果图 话不多说先上效果图,可以先先看看是不是自己想要的 闲聊 闲来无事优化项目时,发现原来的验证码输入框,可扩展性不高,就拿来优化了一下,说说我开始的的思路吧,最开始是想用自定义View实现的,但是发现各种画矩,太烦人了,最后采用的组合控件的形式,Android有现成的控件,用来组合组合就能用,为什么不用呢. 源码 xml ITEM 布局文件(view_auth_code_input_item.xml) <

  • Android仿滴滴出行验证码输入框功能实例代码

    最近公司项目中有一个类似滴滴出行填写验证码的弹框,下面是我撸出来的效果: 中间的那个输入密码的6个框框其实就是用shape画的背景,通过监听EditText获取焦点来改变背景,废话少说,直接上代码吧. 2.效果实现 代码内容比较简单,所以大家可以直接看代码 VerificationCodeInput.java /** * @author hydCoder * @date 2017/9/22 14:39 * @desc 输入验证码的自定义view * @email hyd_coder@163.co

  • Android实现短信验证码输入框

    本文实例为大家分享了Android实现短信验证码输入框的具体代码,供大家参考,具体内容如下 其实用官方自定的那个inputEditText默认带下划线的,然后自己再实行焦点和输入框弹出等操作也可以. 写这个自定义View主要是为了练习. /** * 实现了粘贴事件监听回调的 EditText */ open class ListenPasteEditTextTest : AppCompatEditText { constructor(context: Context): super(contex

  • Android获取短信验证码的实现方法

    先给大家展示下效果图,如果感觉不错,请参考实现思路详解 Android开发中关于短息验证码的设计层出不穷,越来越多的应用为了更好的提高软件的安全性,开始使用通过服务器向用户发送验证码的方式,来保护用户个人信息的安全性.无论是用户注册时的信息验证还是当用户发出找回密码请求时的短信验证,他们的工作原理大致上是一致的,因为项目的需要研究了一下关于这方面的知识,本篇我将带领大家一起实现这一当下流行的设计方案. 众所周知,短信验证需要服务器端生成一个验证码,然后发送到用户输入的手机上,这个过程需要服务器主

  • Android实现短信验证码自动填写功能

    本实例为大家分享了Android实现短信验证码自动填写功能,供大家参考,具体内容如下 实现思路很简单: 1.在需要输入验证码的Activity代码注册监听短信的广播 2.拦截短信,获取其中的验证码 3.回写到EditText private SmsReciver smsReciver = new SmsReciver(); /** 收到短信Action **/ String ACTION_SMS_RECIVER = "android.provider.Telephony.SMS_RECEIVED

  • Android实现短信验证码获取自动填写功能(详细版)

    现在的应用在注册登录或者修改密码中都用到了短信验证码,那在android中是如何实现获取短信验证码并自动填写的呢? 首先,需要要在manifest中注册接收和读取短信的权限: <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> <uses-permission android:name="android.permission.READ_

  • vue实现短信验证码输入框

    本文实例为大家分享了vue实现短信验证码输入框的具体代码,供大家参考,具体内容如下 先上最终效果 (此处代码显示的是短信验证码框的效果   其余部分并未放上去) html <div class="code"> <input id="first" class="inputStyle" v-model="code[0]" style="border-top-left-radius: 12px; bord

  • Android自定义短信验证码组件

    Android自定义短信验证码组件,供大家参考,具体内容如下 效果图 1.布局实现 因为要禁用光标,所以我用TextView代替了EditText,每一行显示的验证码个数由用户决定,所以我这里用线性布局的权重,对TextView进行控制宽度等分,然后设置选中和未选中当前TextView的底部边框,设置高亮颜色背景 2.接受用户输入 我这里使用了TextView,但是怎么接受用户输入的值呢.这里我直接继承了RelativeLayout,然后添加了一个透明的EditText,覆盖在这几个TextVi

  • 手动实现js短信验证码输入框

    前言 本文记录一下自己手动实现的一个前端常见的短信验证码输入组件,从需求到实现逐步优化的过程. 正文 1.需求分析 首先看一下效果图. 首先页面加载的时候,输入框获取焦点,当用户输入一个数字后,焦点自动跳转到第二个框,当四个框全部输入后,模拟发送提交请求,这里用一个弹框提示,输出输入的验证码内容.主流程之外的需求: 输入框内只能输入数字类型,不能输入字母,若强制输入非数字类型按下撤回键时候输入的验证码置空并且把当前焦点跳转至第一个输入框. 2.完整代码实现. 大致思路就是页面加载的时候,给第一个

  • Android实现短信验证码自动填写

    android应用经常会涉及到注册登录功能,而许多的注册登录或修改密码功能常常需要输入短信验证码,通常,用户收到短信需要最小化应用去查看短信再填入验证码,必然比较麻烦,因此有必要能够自动获得下发的短信验证码,方便了用户的操作,用户体验更好. 原理讲解: 主要就是实时获取短信信息.涉及到ContentObserver类的使用.使用ContentProvider来监听短信数据库的变化,在自定义的ContentObserver当中实现onChange的方法进行监听特定手机号的短信,然后进行信息截取在填

  • Android实现短信验证码自动拦截读取功能

    知识准备:  1.观察者模式的理解[文章稍后来到~~]  2.Android的Cursor使用[Android基础]  3.正则表达式使用[Java基础]  4.Handler使用[Android基础] 代码整理: MainActivity.java import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.suppo

  • Android实现自动提取短信验证码功能

    本文实例讲解了Android自动提取短信验证码解决方案,分享给大家供大家参考,具体内容如下 主要功能及优点 1.收到验证码短信后,自动提取短信中的验证码填写到相应输入框 2.可指定一个号码,只读取与他有关短信,避免提取来源错误 3.利用正则表达式,可匹配各种类型验证码 模块集成关键步骤     将auto_getcode_demo中src包里的SMSContentObserver类复制到你的项目src包中 在SMSContentObserver中:    修改正则表达式内容来匹配自己想要获取的字

随机推荐