Android中如何让TextInputLayout提示语的星号保持红色(含浮动标签)?
解决TextInputLayout提示语星号单独设红且浮动时保持红色的方案
这个问题确实挺闹心的——默认的TextInputLayout会在提示转为浮动标签时,把整个标签的颜色统一改成主题色,直接用普通的SpannableString设置一次肯定不管用。不过咱们可以通过自定义SpannableString+监听控件状态重设样式来搞定,我给你两种可行的方案:
方案一:自定义TextInputLayout子类(最稳定)
直接重写控件更新标签状态的方法,每次标签状态变化时强制给星号加上红色样式,从根源上解决覆盖问题:
import android.content.Context import android.graphics.Color import android.text.Spannable import android.text.SpannableString import android.text.style.ForegroundColorSpan import com.google.android.material.textfield.TextInputLayout class RedStarTextInputLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = com.google.android.material.R.attr.textInputLayoutStyle ) : TextInputLayout(context, attrs, defStyleAttr) { // 保存原始提示文本,避免重复处理 private var originalHint: CharSequence? = null override fun setHint(hint: CharSequence?) { originalHint = hint super.setHint(getRedStarSpannable(hint)) } override fun updateLabelState(labelText: CharSequence?, animationEnabled: Boolean) { // 先让父类完成默认逻辑,再强制替换成带红星的文本 super.updateLabelState(getRedStarSpannable(originalHint), animationEnabled) } private fun getRedStarSpannable(text: CharSequence?): SpannableString? { text ?: return null val spannable = SpannableString(text) val starIndex = text.indexOf('*') if (starIndex != -1) { spannable.setSpan( ForegroundColorSpan(Color.RED), starIndex, starIndex + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) } return spannable } }
之后在布局里直接用这个自定义控件代替原生的TextInputLayout就行,不管提示是默认状态还是浮动成标签,星号都会保持红色。
方案二:监听文本变化动态重设样式(无需自定义控件)
如果不想自定义控件,可以通过监听EditText的文本变化,每次状态改变时重新给提示设置带红星的SpannableString:
import android.graphics.Color import android.text.Spannable import android.text.SpannableString import android.text.style.ForegroundColorSpan import android.text.TextWatcher import com.google.android.material.textfield.TextInputLayout // 初始化时调用这个方法 fun setupRedStarHint(textInputLayout: TextInputLayout, originalHint: String) { // 初始设置带红星的提示 textInputLayout.hint = getRedStarSpannable(originalHint) // 监听文本变化,每次变化都重设提示(覆盖控件默认的样式重置) textInputLayout.editText?.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) { textInputLayout.hint = getRedStarSpannable(originalHint) } override fun afterTextChanged(s: Editable?) {} }) } private fun getRedStarSpannable(text: String): SpannableString { val spannable = SpannableString(text) val starIndex = text.indexOf('*') if (starIndex != -1) { spannable.setSpan( ForegroundColorSpan(Color.RED), starIndex, starIndex + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) } return spannable }
调用的时候直接传你的TextInputLayout和原始提示文本(比如setupRedStarHint(myTextInputLayout, "用户名*"))就可以了。
这两种方案都能解决浮动标签时星号变色的问题,第一种更稳定,适合全局复用;第二种更轻量,适合单个控件快速处理。
内容的提问来源于stack exchange,提问作者Manish Singh
相关产品推荐
相关产品推荐

