美文网首页
Android自定义验证码输入框和键盘

Android自定义验证码输入框和键盘

作者: 刺客的幻影 | 来源:发表于2018-09-14 14:45 被阅读0次

先上效果图:


image.png

自定义输入框:

class CellEditText : LinearLayout {

    /**
     * 输入的内容
     */
    var inputNumber: StringBuilder = StringBuilder("")

    /**
     * 输入监听器
     */

    private var mOnInputListener: OnInputListener? = null

    constructor(context: Context?) : super(context) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init()
    }


    private fun init() {
        val view = View.inflate(context, R.layout.cell_edit, null)
        addView(view, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
    }

    /**
     * 输入文本
     */
    fun setText(str: String) {
        Log.d("inputNumber", "str:" + str + "  length:" + inputNumber.length)
        when (inputNumber.length) {
            0 -> {
                inputNumber.append(str)
                tv_pay1.text = str
            }
            1 -> {
                inputNumber.append(str)
                tv_pay2.text = str

            }
            2 -> {
                inputNumber.append(str)
                tv_pay3.text = str


            }
            3 -> {
                inputNumber.append(str)
                tv_pay4.text = str
            }
            4 -> {
                inputNumber.append(str)
                tv_pay5.text = str
            }
            5 -> {
                inputNumber.append(str)
                tv_pay6.text = str

                if (mOnInputListener != null) {
                    mOnInputListener!!.onFinished(inputNumber.toString())
                }
            }

        }

    }

    /**
     * 回退按钮动作
     */
    fun delete() {
        when (inputNumber.length) {
            0 -> {
            }
            1 -> {
                inputNumber.replace(0, 1, "")
                tv_pay1.text = ""
            }
            2 -> {
                inputNumber.replace(1, 2, "")
                tv_pay2.text = ""
            }
            3 -> {
                inputNumber.replace(2, 3, "")
                tv_pay3.text = ""
            }
            4 -> {
                inputNumber.replace(3, 4, "")
                tv_pay4.text = ""
            }
            5 -> {
                inputNumber.replace(4, 5, "")
                tv_pay5.text = ""
            }
            6 -> {
                inputNumber.replace(5, 6, "")
                tv_pay6.text = ""
            }

        }
        Log.d("inputNumber", "length:" + inputNumber.length)
        Toast.makeText(context, inputNumber, Toast.LENGTH_SHORT).show()

    }

    /**
     * 暴露的输入接口
     */
    fun setOnInputListener(listener: OnInputListener) {
        mOnInputListener = listener
    }

    interface OnInputListener {

        fun onFinished(str: String)
    }
}

输入框布局xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/tv_pay1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/cell_edit"
        android:gravity="center"
        android:textColor="#0000ff"
        android:textSize="26sp"
        tools:text="1"
        android:layout_marginLeft="20dp"
        />


    <TextView
        android:id="@+id/tv_pay2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/cell_edit"
        android:gravity="center"
        android:textColor="#0000ff"
        android:layout_marginLeft="20dp"
        android:textSize="26sp"
        tools:text="1" />

    <TextView
        android:id="@+id/tv_pay3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/cell_edit"
        android:gravity="center"
        android:textColor="#0000ff"
        android:layout_marginLeft="20dp"
        android:textSize="26sp"
        tools:text="1" />


    <TextView
        android:id="@+id/tv_pay4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/cell_edit"
        android:gravity="center"
        android:textColor="#0000ff"
        android:layout_marginLeft="20dp"
        android:textSize="26sp"
        tools:text="1" />

    <TextView
        android:id="@+id/tv_pay5"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/cell_edit"
        android:layout_marginLeft="20dp"

        android:gravity="center"
        android:textColor="#0000ff"
        android:textSize="26sp"
        tools:text="1" />


    <TextView
        android:id="@+id/tv_pay6"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_marginLeft="20dp"

        android:background="@drawable/cell_edit"
        android:gravity="center"
        android:textColor="#0000ff"
        android:textSize="26sp"
        android:layout_marginRight="20dp"
        tools:text="1" />

</LinearLayout>

自定义键盘:

class Keyboard : RelativeLayout {
    var mAdapter: MyAdapter? = null
    val keys = arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "0", "完成")

    companion object {
        const val TYPE_COMMON = 996
        const val TYPE_DELET = 965
    }

    constructor(context: Context) : super(context) {
        init()
    }

    constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) {
        init()
    }

    constructor(context: Context, attributeSet: AttributeSet, style: Int) : super(context, attributeSet, style) {
        init()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val widthMode = View.MeasureSpec.getMode(widthMeasureSpec)
        val widthSize = View.MeasureSpec.getSize(widthMeasureSpec)

        // 获取高-测量规则的模式和大小
        val heightMode = View.MeasureSpec.getMode(heightMeasureSpec)
        val heightSize = View.MeasureSpec.getSize(heightMeasureSpec)

        // 设置wrap_content的默认宽 / 高值
        // 默认宽/高的设定并无固定依据,根据需要灵活设置
        // 类似TextView,ImageView等针对wrap_content均在onMeasure()对设置默认宽 / 高值有特殊处理,具体读者可以自行查看
        val mWidth = 400
        val mHeight = 400

        // 当布局参数设置为wrap_content时,设置默认值
        if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            setMeasuredDimension(mWidth, mHeight)
            // 宽 / 高任意一个布局参数为= wrap_content时,都设置默认值
        } else if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
            setMeasuredDimension(mWidth, heightSize)
        } else if (layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            setMeasuredDimension(widthSize, mHeight)
        }

    }

    private fun init() {
        val view = View.inflate(context, R.layout.layout_keyboard, null)
        addView(view, LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
        mAdapter = MyAdapter()
        recycler_view.layoutManager = GridLayoutManager(context, 3)
        recycler_view.addItemDecoration(DefaultItemDecoration(context))
        recycler_view.adapter = mAdapter
    }

    class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)


    inner class MyAdapter : RecyclerView.Adapter<MyViewHolder>() {
        override fun onCreateViewHolder(p0: ViewGroup, viewType: Int): MyViewHolder {
            when (viewType) {
                TYPE_COMMON -> {
                    val itemView = View.inflate(context, R.layout.common_key, null)
                    return MyViewHolder(itemView)
                }
                TYPE_DELET -> {
                    val itemView = View.inflate(context, R.layout.delete_key, null)
                    return MyViewHolder(itemView)
                }

            }
            return MyViewHolder(View(context))

        }

        override fun getItemCount(): Int {
            return keys.size
        }

        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
            when (holder.itemViewType) {
                TYPE_COMMON -> {
                    holder.itemView.findViewById<TextView>(R.id.tv_key).text = keys[position]
                    holder.itemView.findViewById<View>(R.id.tv_key).setOnClickListener {
                        if (mOnItemClickListener != null) {
                            mOnItemClickListener!!.onItemClick(position)
                        }
                    }
                }

                TYPE_DELET -> {
                    holder.itemView.findViewById<View>(R.id.ll_delete).setOnClickListener {
                        mOnItemClickListener!!.onItemClick(position)

                    }
                }
            }

        }

        override fun getItemViewType(position: Int): Int {
            return if (position == 9) {
                TYPE_DELET
            } else {
                TYPE_COMMON
            }
        }

    }

    interface OnItemClickListener {
        fun onItemClick(position: Int)
    }


    private var mOnItemClickListener: OnItemClickListener? = null
    fun setOnItemClickListener(listener: OnItemClickListener) {
        this.mOnItemClickListener = listener
    }

}

输入框监听键盘:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        cell_edit.setOnInputListener(object : CellEditText.OnInputListener {
            override fun onFinished(str: String) {
                Toast.makeText(this@MainActivity, "onFinish:$str", Toast.LENGTH_SHORT).show()
            }
        })

        keyboard.setOnItemClickListener(object : Keyboard.OnItemClickListener {
            override fun onItemClick(position: Int) {
                when (position) {
                    9 -> {//回退
                        cell_edit.delete()
                    }
                    11 -> {//完成
                        Toast.makeText(this@MainActivity, cell_edit.inputNumber, Toast.LENGTH_SHORT).show()
                    }
                    else -> {
                        val value = keyboard.keys[position]
                        cell_edit.setText(value)
                    }
                }
            }
        })

    }
}

需要注意的坑:
自定义keyboard的wrap_content属性会失效,建议把Item的高度写死为X dp,一共有4层,所以将keyboard的高度设置为4X
项目地址:https://github.com/po1arbear/CellEditText

相关文章

网友评论

      本文标题:Android自定义验证码输入框和键盘

      本文链接:https://www.haomeiwen.com/subject/tymugftx.html