Material-components-android: [<TextInputLayout>] How to change underline color programatically?

Created on 21 Sep 2018  路  13Comments  路  Source: material-components/material-components-android

How can I change the underline color from the text input layout?

In Material Design guidelines, it's referred as "Activation indicator" https://material.io/design/components/text-fields.html#anatomy

But I couldn't find any way to change it's color consistently.

Using setBackgroundTint changed the color, but once it's focused the color resets to default. How am I able to change the underline color?

Most helpful comment

@dsn5ft any update on this? where can we track it?

All 13 comments

Need this too. Do you know how to set the underline color in xml? Internet says to use 'colorControlNormal' theme attribute, but it's not working for me.

Ok, currently I found a horrible quickfix, but it kinda suited what I needed. It's just pretty ugly, likely non-performatic and probably causes some unknown bugs right now.

 private fun View.setUnderlineColor() {
        val color = resources.getColor(mTextColorResource)
        this.backgroundTintList = ColorStateList(
                arrayOf(
                        intArrayOf(-android.R.attr.state_focused),
                        intArrayOf(android.R.attr.state_focused)
                ),
                intArrayOf(
                        color,
                        color
                )
        )
    }

But here's the catch: The selected underline color is different from the color that I've set. That happens because (I believe) there are two EditTexts. One for the selected state and one for the unselected state. So you'll have to add that to the focused edit text too:

private fun addFocusChangeListeners() {
        editText.onFocusChange { view, hasFocus ->
            view.setUnderlineColor()
            if(hasFocus) onFocusGain() else onFocusLoss()
        }
    }

But here's another catch: The view won't update that underline color until it's focused. So what I done is focus every view on activity start and unfocus all of them right after:

@Deprecated("In essence, google's code is shitty. Check FixMe comment")
    private fun executeUnderlineFix() {
        /* FIXME This is necessary because Google's code is horrible. There is no way to set an underline color,
            For this reason, we must focus a view and unfocus it. Programmatically, we can only set the own view
            underline color, but when it's focused, the new view underline's color isn't what we set, and we must unfocuus
            it for it to be underlined again. Therefore we need some shenanigans to RequestFocus and Lose Focus, guaranteeing
            that no error is shown.
         */

        val childrenSequence = childrenSequence().filterIsInstance<TextInputLayout>()
        childrenSequence.forEach {
            //Request focus to all
            it.requestFocus()
        }

        this.requestFocus()

        childrenSequence.forEach {
            //Cancel errors for all
            it.error = null
        }
    }

I'm sorry for writing this code. I'm very ashamed of it, but it works :P

That's... actually impressive.

Thanks for the solution, I'll try it out and hopefully the library opens an official API for changing it more easily.

We are currently working on color system updates for all of the components, which should make things like underline color more configurable.

However, for now you should also be able to use a Theme Overlay that sets the colorControlActivated attribute.

Great, @dsn5ft !

I'm looking forward to it.

Should I close this issue?

Sure, closing now.

@dsn5ft any update on this? where can we track it?

we need to be able to get rid of the boxUnderline when the state is BOX_BACKGROUND_FILLED. There's absolutely no way to hide this line if we need to use BOX_BACKGROUND_FILLED.

Any more updates on this functionality? I really want to programmatically change the underline text color without having to update the entire app theme...

When will this be fixed?

Looking for the solution as well....

Using version 1.1.0-alpha09.

Learned that the Activation Indicator's color is set by
<item name="colorOnSurface">[color]</item>
If you cannot change the value of this <item/> in your AppTheme, then

  1. Create a <style/> with <item name="colorOnSurface">[color]</item> set the the color of your background.
  2. Add android:theme="@style/[name of the style created in step 1]" to your TextInputLayout

That made it disappear for me

Was this page helpful?
0 / 5 - 0 ratings