如何在自定义View中实现EditText输入校验及错误提示
实现方案
你可以直接按以下步骤写,逻辑非常直接,不需要找额外参考:
- 第一步:先写自定义View的内部布局
在res/layout目录下新建view_validated_edittext.xml,用merge标签减少布局层级,垂直排列输入框和错误提示:
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <EditText android:id="@+id/et_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:inputType="text" /> <TextView android:id="@+id/tv_error_tip" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:textColor="#F56C6C" android:textSize="12sp" android:visibility="gone" /> </merge>
- 第二步:配置自定义属性,支持在XML里直接设置校验规则
在res/values目录下新建attrs.xml,定义你需要的可配置项:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ValidatedEditText"> <attr name="minLength" format="integer" /> <attr name="maxLength" format="integer" /> <attr name="errorTooShort" format="string" /> <attr name="errorTooLong" format="string" /> <attr name="inputHint" format="string" /> </declare-styleable> </resources>
- 第三步:写自定义View的核心逻辑
直接继承垂直方向的LinearLayout,加载布局、读取属性、绑定输入监听、实现校验逻辑即可,以下是Kotlin实现,Java逻辑完全一致:
import android.content.Context import android.text.Editable import android.text.TextWatcher import android.util.AttributeSet import android.view.LayoutInflater import android.widget.EditText import android.widget.LinearLayout import android.widget.TextView class ValidatedEditText @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr) { private val etInput: EditText private val tvErrorTip: TextView private var minLen = 0 private var maxLen = Int.MAX_VALUE private var errorShortTip = "输入内容太短" private var errorLongTip = "输入内容太长" init { orientation = VERTICAL // 加载布局 LayoutInflater.from(context).inflate(R.layout.view_validated_edittext, this, true) etInput = findViewById(R.id.et_input) tvErrorTip = findViewById(R.id.tv_error_tip) // 读取XML里配置的属性 attrs?.let { val ta = context.obtainStyledAttributes(it, R.styleable.ValidatedEditText) minLen = ta.getInt(R.styleable.ValidatedEditText_minLength, 0) maxLen = ta.getInt(R.styleable.ValidatedEditText_maxLength, Int.MAX_VALUE) ta.getString(R.styleable.ValidatedEditText_errorTooShort)?.let { tip -> errorShortTip = tip } ta.getString(R.styleable.ValidatedEditText_errorTooLong)?.let { tip -> errorLongTip = tip } ta.getString(R.styleable.ValidatedEditText_inputHint)?.let { hint -> etInput.hint = hint } ta.recycle() } // 绑定输入监听,输入变化时自动触发校验 etInput.addTextChangedListener(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?) { validateInput() } }) } // 核心校验逻辑 private fun validateInput(): Boolean { val content = etInput.text?.toString()?.trim() ?: "" return when { content.length < minLen -> { tvErrorTip.visibility = VISIBLE tvErrorTip.text = errorShortTip false } content.length > maxLen -> { tvErrorTip.visibility = VISIBLE tvErrorTip.text = errorLongTip false } else -> { tvErrorTip.visibility = GONE true } } } // 对外暴露的方法,供外部比如提交按钮点击时获取校验结果 fun isInputValid(): Boolean = validateInput() // 对外暴露获取输入内容的方法 fun getInputContent(): String = etInput.text?.toString()?.trim() ?: "" // 支持动态修改校验规则 fun setLengthLimit(min: Int, max: Int) { minLen = min maxLen = max validateInput() } }
- 第四步:直接在布局里使用即可
<com.your.package.ValidatedEditText android:id="@+id/et_username" android:layout_width="match_parent" android:layout_height="wrap_content" app:minLength="3" app:maxLength="12" app:inputHint="请输入用户名" app:errorTooShort="用户名长度不能少于3位" app:errorTooLong="用户名长度不能超过12位"/>
如果需要加其他校验规则(比如手机号、邮箱格式校验),直接在
validateInput方法里加判断分支、对应错误文案即可,不需要改整体结构。如果需要输入框自带清空按钮、密码明暗文切换之类的功能,直接在布局里的EditText旁边加对应控件,在自定义View里绑定点击事件就行。
内容的提问来源于stack exchange,提问作者HeraGonz
相关产品推荐
相关产品推荐

