美文网首页
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