欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Android实现短信验证码输入框

程序员文章站 2022-06-16 21:29:15
本文实例为大家分享了android实现短信验证码输入框的具体代码,供大家参考,具体内容如下其实用官方自定的那个inputedittext默认带下划线的,然后自己再实行焦点和输入框弹出等操作也可以。写这...

本文实例为大家分享了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)
}

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