Android自定義view實現(xiàn)TextView方形輸入框
本文實例為大家分享了Android自定義view實現(xiàn)TextView方形輸入框的具體代碼,供大家參考,具體內(nèi)容如下
先奉上最終效果圖
實現(xiàn)思路分析:
1、 使用一個LinearLayout用來填充每一個小方格,通過動態(tài)添加,實現(xiàn)出需要數(shù)量的輸入框
2、 在LinearLayout上覆蓋一層大小和LinearLayout大小完全一致的EditText,用來接口輸入信息,設置EditText輸入背景和文字為透明,并設置不展示光標,
3、 監(jiān)聽EditText的內(nèi)容變化,和LinearLayout的內(nèi)容綁定,實現(xiàn)每次輸入都由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>
在代碼中動態(tài)創(chuàng)建LinearLayout子布局填充,并綁定監(jiān)聽
private fun initContainer() { //動態(tài)設置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() //動態(tài)添加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() } } }
核心代碼就到這里了,為了方便擴展,可以在加入自定義屬性,動態(tài)設置擴展效果,這里就不說明了,直接看代碼即可
最后放上完整源代碼:
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>
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android之日期時間選擇控件DatePicker和TimePicker實例
本篇文章主要介紹了Android之日期時間選擇控件DatePicker和TimePicker實例,具有一定的參考價值,有興趣的可以了解一下2017-05-05Android中Fragment與Activity的生命周期對比
這篇文章主要介紹了Android中Fragment與Activity的生命周期對比,Fragment是在Activity的基礎之上進行設計的,比Activity多出幾個控制生命周期的回調(diào)函數(shù),需要的朋友可以參考下2016-02-02Android Socket實現(xiàn)多個客戶端即時通信聊天
這篇文章主要為大家詳細介紹了Android Socket實現(xiàn)多個客戶端即時通信聊天,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04Android ConnectivityManager網(wǎng)絡管理詳解
在android平臺中ConnectivityManager主要負責查詢網(wǎng)絡連接狀態(tài)以及在連接狀態(tài)有變化的時候發(fā)出通知,這篇文章主要介紹了Android ConnectivityManager網(wǎng)絡管理2022-11-11Android自定義View 使用PathMeasure簡單模仿系統(tǒng)ProgressBar(四)
這篇文章主要為大家詳細介紹了Android自定義View,使用PathMeasure簡單模仿系統(tǒng)ProgressBar,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03