如何在TextInputLayout中实现类似setError()的成功状态展示
实现自定义TextInputLayout的成功/错误/辅助文本模式
核心思路
不用在运行时修改主题,而是通过动态切换颜色资源+复用TextInputLayout的错误状态UI逻辑实现成功状态与错误状态视觉一致,同时利用SavedStateHandle保存状态,避免配置变更丢失。
1. 自定义CustomTextInputLayout类
继承官方TextInputLayout,添加状态枚举、状态保存逻辑,实现三个目标方法:
class CustomTextInputLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = com.google.android.material.R.attr.textInputLayoutStyle ) : TextInputLayout(context, attrs, defStyleAttr) { enum class Mode { SUCCESS, ERROR, HELPER } private var currentMode: Mode = Mode.HELPER private val savedStateHandle = SavedStateHandle.createSavedStateHandle( ViewTreeSavedStateRegistryOwner.get(this), id.toString() ) // 初始化时恢复保存的状态 init { currentMode = savedStateHandle.get<Mode>("current_mode") ?: Mode.HELPER updateUIForCurrentMode() } fun setSuccessMode(message: String? = null) { currentMode = Mode.SUCCESS savedStateHandle.set("current_mode", currentMode) updateUIForCurrentMode(message) } fun setErrorMode(message: String? = null) { currentMode = Mode.ERROR savedStateHandle.set("current_mode", currentMode) updateUIForCurrentMode(message) } fun setHelperTextMode(message: String? = null) { currentMode = Mode.HELPER savedStateHandle.set("current_mode", currentMode) updateUIForCurrentMode(message) } private fun updateUIForCurrentMode(message: String? = null) { when(currentMode) { Mode.SUCCESS -> { // 复用错误状态的UI逻辑,替换颜色为成功色 setError(message) val successColor = context.getColor(R.color.success_color) boxStrokeColor = successColor defaultHintTextColor = ColorStateList.valueOf(successColor) helperTextTextColor = ColorStateList.valueOf(successColor) } Mode.ERROR -> { // 原生错误状态,恢复主题错误色 setError(message) val errorColor = ThemeUtils.getColorFromAttr(context, com.google.android.material.R.attr.colorError) boxStrokeColor = errorColor defaultHintTextColor = ColorStateList.valueOf(errorColor) helperTextTextColor = ColorStateList.valueOf(errorColor) } Mode.HELPER -> { // 清除错误,恢复默认辅助文本状态 error = null helperText = message val defaultTextColor = ThemeUtils.getColorFromAttr(context, android.R.attr.textColorSecondary) boxStrokeColor = ThemeUtils.getColorFromAttr(context, com.google.android.material.R.attr.colorOutline) defaultHintTextColor = ColorStateList.valueOf(defaultTextColor) helperTextTextColor = ColorStateList.valueOf(defaultTextColor) } } } }
2. 主题属性颜色工具类
用于获取主题中的颜色,避免硬编码:
object ThemeUtils { fun getColorFromAttr(context: Context, attrRes: Int): Int { val typedValue = TypedValue() context.theme.resolveAttribute(attrRes, typedValue, true) return typedValue.data } }
3. 定义成功色资源
在res/values/colors.xml中添加成功色:
<color name="success_color">#4CAF50</color>
关键细节说明
- 复用
setError()方法:利用TextInputLayout错误状态已有的UI变化逻辑(边框高亮、提示色切换、消息显示),仅替换颜色即可实现成功状态与错误状态视觉一致 - 状态持久化:通过
SavedStateHandle保存当前模式,确保屏幕旋转、配置变更后状态不丢失 - 无主题修改:全程通过动态覆盖颜色属性实现,避免运行时切换主题的复杂逻辑
内容的提问来源于stack exchange,提问作者rupinderjeet
相关产品推荐
相关产品推荐

