327

I am using appcompat v7 to get the look consistent on Android 5 and less. It works rather well. However I cannot figure out how to change the bottom line color and the accent color for EditTexts. Is it possible?

I have tried to define a custom android:editTextStyle (cf. below) but I only succeeded to change the full background color or text color but not the bottom line nor the accent color. Is there a specific property value to use? do I have to use a custom drawable image through the android:background property? is it not possible to specify a color in hexa?

 <style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="android:editTextStyle">@style/Widget.App.EditText</item> </style> <style name="Widget.App.EditText" parent="Widget.AppCompat.EditText"> ??? </style> 

According to android API 21 sources, EditTexts with material design seem to use colorControlActivated and colorControlNormal. Therefore, I have tried to override these properties in the previous style definition but it has no effect. Probably appcompat does not use it. Unfortunately, I cannot find the sources for the last version of appcompat with material design.

4
  • define your theme for edit text Commented Oct 26, 2014 at 15:37
  • Thank you for your suggestion but I have already do that. I have updated my question to show what I have already tried to do. My issue is about the attribute to use in the theme style to change the edittext bottom line color. Ideally, I am looking for a solution where I can directly specify the color in hexa. Commented Oct 26, 2014 at 15:49
  • None of these answers are working for me on 4.3. Do you have a working solution? Commented Dec 15, 2015 at 16:54
  • I had to extend AppCompatEditText, apparently. Commented Nov 28, 2016 at 15:19

25 Answers 25

489

Finally, I have found a solution. It simply consists of overriding the value for colorControlActivated, colorControlHighlight and colorControlNormal in your app theme definition and not your edittext style. Then, think to use this theme for whatever activity you desire. Below is an example:

<style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorControlNormal">#c5c5c5</item> <item name="colorControlActivated">@color/accent</item> <item name="colorControlHighlight">@color/accent</item> </style> 
Sign up to request clarification or add additional context in comments.

10 Comments

I see the color of the menu hamburger, back button, and scroll bar have changed to colorControlNormal.
This changes the color of the bottom line but it also changes every other control like check boxes, radio buttons etc. It also changes every EditText across the whole Application / Activity. If you want to change the bottom line of a single EditText (like I do) then you have to override the android:background property for that EditText. There's no other way AFAIK.
If you are using the AppCompat v22 support library, you can specify the theme in the EditText like: android:theme="@style/Theme.App.Base. This will ensure the style won't also affect other views in your layouts that you don't want to change.
Didn't work on Jelly Bean (4.2) but worked on Lollipop
The activity should inherit from AppCompatActivity. It will not work if it inherits from Activity.
|
189

I felt like this needed an answer in case somebody wanted to change just a single edittext. I do it like this:

editText.getBackground().mutate().setColorFilter(ContextCompat.getColor(context, R.color.your_color), PorterDuff.Mode.SRC_ATOP); 

9 Comments

But how can i reset to default background, i've got a lot of bugs after calling editText.getBackground().resetColorFilter() on Lollipop?
Caution! adding this may cause to change color of editText across ALL app. Tested on Nexus 5. OS 6.0.1.
@AlexPerevozchykov you might be right. Try adding .mutate() after .getBackground(). That should do it.
@hordurh yes, it was it, I've received this suggestion little bit earlier, drawables share one pool so before changing we need to mutate it
If i use edittext, it is work but this method doesn't work with app compat edittext on lollipop. do you know how can i resolve the issue?
|
148

While Laurents solution is correct, it comes with some drawbacks as described in the comments since not only the bottom line of the EditText gets tinted but the Back Button of the Toolbar, CheckBoxes etc. as well.

Luckily v22.1 of appcompat-v7 introduced some new possibilities. Now it's possible to assign a specific theme only to one view. Straight from the Changelog:

Deprecated use of app:theme for styling Toolbar. You can now use android:theme for toolbars on all API level 7 and higher devices and android:theme support for all widgets on API level 11 and higher devices.

So instead of setting the desired color in a global theme, we create a new one and assign it only to the EditText.

Example:

<style name="MyEditTextTheme"> <!-- Used for the bottom line when not selected / focused --> <item name="colorControlNormal">#9e9e9e</item> <!-- colorControlActivated & colorControlHighlight use the colorAccent color by default --> </style> 

<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/MyEditTextTheme"/> 

5 Comments

I don't think this is necessary. colorControlNormal without the android prefix uses the appcompat method to tint widgets while with the prefix it fallsback to the system method and this is only available in API 21+ devices.
hmm, I tested on my lollipop device and it wont tint to the custom color unless you implement it in v21 styles with the android namespace also.
I am using 22.2.0 version of AppCompat but this trick is not working :(
using <item name="colorAccent">#000000</item> worked for me instead of colorControlNormal.
Perfect to change only one edit text in the app! (Exactly what I needed! Thanks)
106

This can be changed in XML by using:

For Reference API >= 21 compatibility use:

android:backgroundTint="@color/blue" 

For backward API < 21 compatibility use:

app:backgroundTint="@color/blue" 

6 Comments

Yes, however this works only for android API versions 21+ (kitkat & lolipop). One would probably try to create a backward compatible solution.
Just use backgroundTint="@color/blue" instead of android:backgroundTint="@color/blue" for backward compatible support
@KishanVaghela, instead of using android:backgroundTint="@color/blue", use app:backgroundTint="@color/blue" to support pre-Lollipop devices, thanks for your comment !
@blueware If you want to use it in style, then we dont need to use "app".
add tools:ignore="MissingPrefix" if a red underline pop under app:backgroundTint="<your color>"
|
48

Here is the solution for API < 21 and above

Drawable drawable = yourEditText.getBackground(); // get current EditText drawable drawable.setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP); // change the drawable color if(Build.VERSION.SDK_INT > 16) { yourEditText.setBackground(drawable); // set the new drawable to EditText }else{ yourEditText.setBackgroundDrawable(drawable); // use setBackgroundDrawable because setBackground required API 16 } 

enter image description here

Hope it help

3 Comments

@CoolMind sorry for late response. I have check this code again in support library 24.2.1, 25.1.1, 25.2.0 for device < 21 and > 21 and it still working. Please check this simple demo drive.google.com/file/d/0B_poNaia6t8kSzU3bDFVazRSSDA/…. I don't know why this code not work for you so please let me know. thank you
@Renjith sorry for late response, please check my comment above
How do you reset the color to default with this code?
35

The accepted answer is a bit more per style basis thing, but the most efficient thing to do is to add the colorAccent attribute in your AppTheme style like this:

<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorAccent">@color/colorAccent</item> <item name="android:editTextStyle">@style/EditTextStyle</item> </style> <style name="EditTextStyle" parent="Widget.AppCompat.EditText"/> 

The colorAccent attribute is used for widget tinting throughout the app and thus should be used for consistency

2 Comments

@Tomasz it doesnt requre API 21+ because the parent theme is AppCompat which goes down to API 7
Ughhh. Thanks for this, I was using name="android:colorAccent" mistakenly
29

If you are using appcompat-v7:22.1.0+ you can use the DrawableCompat to tint your widgets

 public static void tintWidget(View view, int color) { Drawable wrappedDrawable = DrawableCompat.wrap(view.getBackground()); DrawableCompat.setTint(wrappedDrawable.mutate(), getResources().getColor(color)); view.setBackgroundDrawable(wrappedDrawable); } 

2 Comments

what a lifesaver this is awesome, a shame it's not well know
Please move down and see my answer for design library 23.2.0. This method is useless right now.
22

<!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="colorControlNormal">@color/colorAccent</item> <item name="colorControlActivated">@color/colorAccent</item> <item name="colorControlHighlight">@color/colorAccent</item> </style> 

3 Comments

It works! As the question asks, it should be resolve in the style/theme, this should be the correct answer.
I agree. this should be the correct answer since it is a global solution
This is inconvenient if different controls need different colors.
21

Use:

<EditText app:backgroundTint="@color/blue"/> 

This will support pre-Lollipop devices not only +21

3 Comments

@powder366, can you post your app main theme?
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
@powder366, try this: <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> and it should work
12

One quick solution for your problem is to look in yourappspackage/build/intermediates/exploded-aar/com.android.support/appcompat-v7/res/drawable/ for abc_edit_text_material.xml and copy that xml file in your drawable folder. Then you can change the colour of the 9 patch files from inside this selector, in order to match your preferences.

Comments

9

It's very easy just add android:backgroundTint attribute in your EditText.

android:backgroundTint="@color/blue" android:backgroundTint="#ffffff" android:backgroundTint="@color/red" <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:backgroundTint="#ffffff"/> 

3 Comments

backgroundTint above API leve 21
ViewCompat.setBackgroundTintList(editText, ColorStateList.valueOf(Color.YELLOW))
app:backgroundTint="@color/blue" works on all api levels.. although for whatever reason it is still turning to a different color when selected XD
8

Here is a part of source code of TextInputLayout in support design library(UPDATED for version 23.2.0), which changes EditText's bottom line color in a simpler way:

private void updateEditTextBackground() { ensureBackgroundDrawableStateWorkaround(); final Drawable editTextBackground = mEditText.getBackground(); if (editTextBackground == null) { return; } if (mErrorShown && mErrorView != null) { // Set a color filter of the error color editTextBackground.setColorFilter( AppCompatDrawableManager.getPorterDuffColorFilter( mErrorView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN)); } ... } 

It seems that all of above code become useless right now in 23.2.0 if you want to change the color programatically.

And if you want to support all platforms, here is my method:

/** * Set backgroundTint to {@link View} across all targeting platform level. * @param view the {@link View} to tint. * @param color color used to tint. */ public static void tintView(View view, int color) { final Drawable d = view.getBackground(); final Drawable nd = d.getConstantState().newDrawable(); nd.setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter( color, PorterDuff.Mode.SRC_IN)); view.setBackground(nd); } 

1 Comment

What is AppCompatDrawableManager? setBackground requires API 16.
8

I too was stuck on this problem for too long.

I required a solution that worked for versions both above and below v21.

I finally discovered a very simple perhaps not ideal but effective solution: Simply set the background colour to transparent in the EditText properties.

<EditText android:background="@android:color/transparent"/> 

I hope this saves someone some time.

2 Comments

This is changing whole background color, and we want to change only underline color.
@shahzain ali The Underline of EditText is a background. Its gone if you set it to null. And thats why backgroundTint will worked(but it will not change color when activated)
7

For me I modified both the AppTheme and a value colors.xml Both the colorControlNormal and the colorAccent helped me change the EditText border color. As well as the cursor, and the "|" when inside an EditText.

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorControlNormal">@color/yellow</item> <item name="colorAccent">@color/yellow</item> </style> 

Here is the colors.xml

<?xml version="1.0" encoding="utf-8"?> <resources> <color name="yellow">#B7EC2A</color> </resources> 

I took out the android:textCursorDrawable attribute to @null that I placed inside the editText style. When I tried using this, the colors would not change.

1 Comment

This should be the answer
6

You can set background of edittext to a rectangle with minus padding on left, right and top to achieve this. Here is the xml example:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:top="-1dp" android:left="-1dp" android:right="-1dp" android:bottom="1dp" > <shape android:shape="rectangle"> <stroke android:width="1dp" android:color="#6A9A3A"/> </shape> </item> </layer-list> 

Replace the shape with a selector if you want to provide different width and color for focused edittext.

Comments

5

I worked out a working solution to this problem after 2 days of struggle, below solution is perfect for them who want to change few edit text only, change/toggle color through java code, and want to overcome the problems of different behavior on OS versions due to use setColorFilter() method.

 import android.content.Context; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.support.v4.content.ContextCompat; import android.support.v7.widget.AppCompatDrawableManager; import android.support.v7.widget.AppCompatEditText; import android.util.AttributeSet; import com.newco.cooltv.R; public class RqubeErrorEditText extends AppCompatEditText { private int errorUnderlineColor; private boolean isErrorStateEnabled; private boolean mHasReconstructedEditTextBackground; public RqubeErrorEditText(Context context) { super(context); initColors(); } public RqubeErrorEditText(Context context, AttributeSet attrs) { super(context, attrs); initColors(); } public RqubeErrorEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initColors(); } private void initColors() { errorUnderlineColor = R.color.et_error_color_rule; } public void setErrorColor() { ensureBackgroundDrawableStateWorkaround(); getBackground().setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter( ContextCompat.getColor(getContext(), errorUnderlineColor), PorterDuff.Mode.SRC_IN)); } private void ensureBackgroundDrawableStateWorkaround() { final Drawable bg = getBackground(); if (bg == null) { return; } if (!mHasReconstructedEditTextBackground) { // This is gross. There is an issue in the platform which affects container Drawables // where the first drawable retrieved from resources will propogate any changes // (like color filter) to all instances from the cache. We'll try to workaround it... final Drawable newBg = bg.getConstantState().newDrawable(); //if (bg instanceof DrawableContainer) { // // If we have a Drawable container, we can try and set it's constant state via // // reflection from the new Drawable // mHasReconstructedEditTextBackground = // DrawableUtils.setContainerConstantState( // (DrawableContainer) bg, newBg.getConstantState()); //} if (!mHasReconstructedEditTextBackground) { // If we reach here then we just need to set a brand new instance of the Drawable // as the background. This has the unfortunate side-effect of wiping out any // user set padding, but I'd hope that use of custom padding on an EditText // is limited. setBackgroundDrawable(newBg); mHasReconstructedEditTextBackground = true; } } } public boolean isErrorStateEnabled() { return isErrorStateEnabled; } public void setErrorState(boolean isErrorStateEnabled) { this.isErrorStateEnabled = isErrorStateEnabled; if (isErrorStateEnabled) { setErrorColor(); invalidate(); } else { getBackground().mutate().clearColorFilter(); invalidate(); } } } 

Uses in xml

<com.rqube.ui.widget.RqubeErrorEditText android:id="@+id/f_signup_et_referral_code" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_toEndOf="@+id/referral_iv" android:layout_toRightOf="@+id/referral_iv" android:ems="10" android:hint="@string/lbl_referral_code" android:imeOptions="actionNext" android:inputType="textEmailAddress" android:textSize="@dimen/text_size_sp_16" android:theme="@style/EditTextStyle"/> 

Add lines in style

<style name="EditTextStyle" parent="android:Widget.EditText"> <item name="android:textColor">@color/txt_color_change</item> <item name="android:textColorHint">@color/et_default_color_text</item> <item name="colorControlNormal">@color/et_default_color_rule</item> <item name="colorControlActivated">@color/et_engagged_color_rule</item> </style> 

java code to toggle color

myRqubeEditText.setErrorState(true); myRqubeEditText.setErrorState(false); 

Comments

5

In Activit.XML add the code

<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPersonName" android:ems="10" android:id="@+id/editText" android:hint="Informe o usuário" android:backgroundTint="@android:color/transparent"/> 

Where BackgroundTint=color for your desired colour

Comments

5

I use this method to change the color of the line with PorterDuff, with no other drawable.

public void changeBottomColorSearchView(int color) { int searchPlateId = mSearchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null); View searchPlate = mSearchView.findViewById(searchPlateId); searchPlate.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN); } 

1 Comment

Does a similar identifier exist to access the bottom line of a simple EditText ?
4

If you want change bottom line without using app colors, use these lines in your theme:

<item name="android:editTextStyle">@android:style/Widget.EditText</item> <item name="editTextStyle">@android:style/Widget.EditText</item> 

I don't know another solution.

Comments

2

I was absolutely baffled by this problem. I had tried everything in this thread, and in others, but no matter what I did I could not change the color of the underline to anything other than the default blue.

I finally figured out what was going on. I was (incorrectly) using android.widget.EditText when making a new instance (but the rest of my components were from the appcompat library). I should have used android.support.v7.widget.AppCompatEditText. I replaced new EditText(this) with new AppCompatEditText(this) and the problem was instantly solved. It turns out, if you are actually using AppCompatEditText, it will just respect the accentColor from your theme (as mentioned in several comments above) and no additional configuration is necessary.

Comments

2

This is the easiest and most efficient/reusable/works on all APIs
Create a custom EditText class like so:

public class EditText extends android.widget.EditText { public EditText(Context context) { super(context); init(); } public EditText(Context context, AttributeSet attrs) { super(context, attrs); init(); } public EditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { getBackground().mutate().setColorFilter(ContextCompat.getColor(getContext(), R.color.colorAccent), PorterDuff.Mode.SRC_ATOP); } } 

Then use it like this:

 <company.com.app.EditText android:layout_width="200dp" android:layout_height="wrap_content"/> 

Comments

2

To change the EditText background dynamically, you can use ColorStateList.

int[][] states = new int[][] { new int[] { android.R.attr.state_enabled}, // enabled new int[] {-android.R.attr.state_enabled}, // disabled new int[] {-android.R.attr.state_checked}, // unchecked new int[] { android.R.attr.state_pressed} // pressed }; int[] colors = new int[] { Color.BLACK, Color.RED, Color.GREEN, Color.BLUE }; ColorStateList colorStateList = new ColorStateList(states, colors); 

Credits: This SO answer about ColorStateList is awesome.

2 Comments

And what method to use? setBackgroundTintList? It requires API 21.
setSupportBackgroundTintList for older API verisons.
2

You can use just backgroundTint for change bottom line color of edit text

 android:backgroundTint="#000000" 

example :

 <EditText android:id="@+id/title1" android:layout_width="match_parent" android:layout_height="wrap_content" android:backgroundTint="#000000" /> 

Comments

0

Add app:backgroundTint for below api level 21. Otherwise use android:backgroundTint.

For below api level 21.

<EditText android:id="@+id/edt_name" android:layout_width="300dp" android:layout_height="wrap_content" android:textColor="#0012ff" app:backgroundTint="#0012ff"/> 

For higher than api level 21.

<EditText android:id="@+id/edt_name" android:layout_width="300dp" android:layout_height="wrap_content" android:textColor="#0012ff" android:backgroundTint="#0012ff"/> 

Comments

-2

Please modify this method according to your need. This worked for me!

private boolean validateMobilenumber() { if (mobilenumber.getText().toString().trim().isEmpty() || mobilenumber.getText().toString().length() < 10) { input_layout_mobilenumber.setErrorEnabled(true); input_layout_mobilenumber.setError(getString(R.string.err_msg_mobilenumber)); // requestFocus(mobilenumber); return false; } else { input_layout_mobilenumber.setError(null); input_layout_mobilenumber.setErrorEnabled(false); mobilenumber.setBackground(mobilenumber.getBackground().getConstantState().newDrawable()); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.