You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:22:06