Android自定义view实现TextView方形输入框
本文实例为大家分享了Android自定义view实现TextView方形输入框的具体代码,供大家参考,具体内容如下
先奉上最终效果图
实现思路分析:
1、 使用一个LinearLayout用来填充每一个小方格,通过动态添加,实现出需要数量的输入框
2、 在LinearLayout上覆盖一层大小和LinearLayout大小完全一致的EditText,用来接口输入信息,设置EditText输入背景和文字为透明,并设置不展示光标,
3、 监听EditText的内容变化,和LinearLayout的内容绑定,实现每次输入都由LinearLayout的子布局展示出来
布局文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content"> <LinearLayout android:orientation="horizontal" android:id="@+id/rvContentList" android:gravity="center" android:showDividers="middle" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <EditText android:id="@+id/inputReal" android:inputType="number" android:background="@android:color/transparent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/transparent"/> </RelativeLayout>
在代码中动态创建LinearLayout子布局填充,并绑定监听
private fun initContainer() { //动态设置EditText的大小 inputReal = findViewById(R.id.inputReal) rvContentList = findViewById(R.id.rvContentList) inputReal.width = (dividerDrawable?.minimumWidth ?: 0 * (verifyCodeLen - 1)) + inputBoxSize * verifyCodeLen inputReal.height = inputBoxSize inputReal.setTextSize(TypedValue.COMPLEX_UNIT_PX, inputTextSize * 1.0F) //禁用光标 inputReal.isCursorVisible = false inputReal.filters = arrayOf(InputFilter.LengthFilter(verifyCodeLen)) inputTextView.clear() //动态添加LinearLayout之间的分割线 dividerDrawable?.let { it.setBounds(0, 0, it.minimumWidth, it.minimumHeight) rvContentList.dividerDrawable = it } for (i in 0 until verifyCodeLen) { val textView = TextView(context) textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, inputTextSize * 1.0F) textView.width = inputBoxSize textView.height = inputBoxSize textView.gravity = Gravity.CENTER textView.isFocusable = false textView.textColor = inputTextColor textView.backgroundResource = itemSelector inputTextView.add(textView) } inputTextView.forEach { rvContentList.addView(it) } }
inputReal.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(p0: Editable?) { setVerifyCodeInputValue(p0.toString()) if (p0.toString().length == verifyCodeLen) { onCompleteListener?.onComplete(p0.toString()) } } override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } })
private fun setVerifyCodeInputValue(inputText: String) { inputTextView.forEach { it.text = "" it.isSelected = false } inputTextView.forEachIndexed { index, textView -> if (inputText.length > index) { textView.isSelected = true textView.text = inputText[index].toString() } } }
核心代码就到这里了,为了方便扩展,可以在加入自定义属性,动态设置扩展效果,这里就不说明了,直接看代码即可
最后放上完整源代码:
package org.fireking.ap.custom.viewgroup.view import android.content.Context import android.content.res.TypedArray import android.graphics.Color import android.graphics.drawable.Drawable import android.text.Editable import android.text.InputFilter import android.text.Spanned import android.text.TextWatcher import android.util.AttributeSet import android.util.Log import android.util.TypedValue import android.view.Gravity import android.view.LayoutInflater import android.widget.* import androidx.core.view.forEach import androidx.recyclerview.widget.RecyclerView import org.fireking.ap.R import org.jetbrains.anko.backgroundColor import org.jetbrains.anko.backgroundResource import org.jetbrains.anko.textColor class VerifyCodeInputLayout(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : RelativeLayout(context, attrs, defStyleAttr) { private lateinit var inputReal: EditText private lateinit var rvContentList: LinearLayout private var onCompleteListener: OnCompleteListener? = null private var verifyCodeLen = 0 private var inputTextSize: Int = 0 private var inputTextColor: Int = 0 private var inputBoxSize: Int = 0 private var verifyInputLayoutHeight = 0 private var dividerDrawable: Drawable? = null private var itemSelector: Int = R.drawable.verify_code_text_selector private var inputTextView = ArrayList<TextView>(4) constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) { LayoutInflater.from(context).inflate(R.layout.verify_code_input_layout, this, true) //设置默认值 verifyCodeLen = 4 inputTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16.0F, resources.displayMetrics).toInt() inputTextColor = Color.parseColor("#FF333333") inputBoxSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50F, resources.displayMetrics).toInt() dividerDrawable = context.resources.getDrawable(R.drawable.linearlayout_divider) //获取自定义属性值 val a = context.obtainStyledAttributes(attrs, R.styleable.VerifyCodeInputLayout) if (a.hasValue(R.styleable.VerifyCodeInputLayout_textSize)) { inputTextSize = a.getDimensionPixelSize(R.styleable.VerifyCodeInputLayout_textSize, inputTextSize) } if (a.hasValue(R.styleable.VerifyCodeInputLayout_textColor)) { inputTextColor = a.getColor(R.styleable.VerifyCodeInputLayout_textColor, Color.parseColor("#FF333333")) } if (a.hasValue(R.styleable.VerifyCodeInputLayout_inputBoxSize)) { inputBoxSize = a.getDimensionPixelSize( R.styleable.VerifyCodeInputLayout_inputBoxSize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 44F, resources.displayMetrics).toInt() ) } if (a.hasValue(R.styleable.VerifyCodeInputLayout_dividerDrawable)) { dividerDrawable = a.getDrawable(R.styleable.VerifyCodeInputLayout_dividerDrawable) } if (a.hasValue(R.styleable.VerifyCodeInputLayout_itemSelector)) { itemSelector = a.getResourceId(R.styleable.VerifyCodeInputLayout_itemSelector, itemSelector) } if (a.hasValue(R.styleable.VerifyCodeInputLayout_maxLength)) { verifyCodeLen = a.getInt(R.styleable.VerifyCodeInputLayout_maxLength, 4) } a.recycle() } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) verifyInputLayoutHeight = measuredHeight } fun setOnCompleteListener(onCompleteListener: OnCompleteListener) { this.onCompleteListener = onCompleteListener } override fun onFinishInflate() { super.onFinishInflate() initContainer() initListener() } private fun initListener() { inputReal.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(p0: Editable?) { setVerifyCodeInputValue(p0.toString()) if (p0.toString().length == verifyCodeLen) { onCompleteListener?.onComplete(p0.toString()) } } override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } }) } private fun setVerifyCodeInputValue(inputText: String) { inputTextView.forEach { it.text = "" it.isSelected = false } inputTextView.forEachIndexed { index, textView -> if (inputText.length > index) { textView.isSelected = true textView.text = inputText[index].toString() } } } private fun initContainer() { inputReal = findViewById(R.id.inputReal) rvContentList = findViewById(R.id.rvContentList) inputReal.width = (dividerDrawable?.minimumWidth ?: 0 * (verifyCodeLen - 1)) + inputBoxSize * verifyCodeLen inputReal.height = inputBoxSize inputReal.setTextSize(TypedValue.COMPLEX_UNIT_PX, inputTextSize * 1.0F) inputReal.isCursorVisible = false inputReal.filters = arrayOf(InputFilter.LengthFilter(verifyCodeLen)) inputTextView.clear() dividerDrawable?.let { it.setBounds(0, 0, it.minimumWidth, it.minimumHeight) rvContentList.dividerDrawable = it } for (i in 0 until verifyCodeLen) { val textView = TextView(context) textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, inputTextSize * 1.0F) textView.width = inputBoxSize textView.height = inputBoxSize textView.gravity = Gravity.CENTER textView.isFocusable = false textView.textColor = inputTextColor textView.backgroundResource = itemSelector inputTextView.add(textView) } inputTextView.forEach { rvContentList.addView(it) } } interface OnCompleteListener { fun onComplete(content: String) } }
自定义属性
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="VerifyCodeInputLayout"> <attr name="textSize" format="dimension"/> <attr name="textColor" format="color"/> <attr name="inputBoxSize" format="dimension"/> <attr name="dividerDrawable" format="reference"/> <attr name="maxLength" format="integer"/> <attr name="itemSelector" format="reference"/> </declare-styleable> </resources>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
赞 (0)