326

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.

l-l
  • 3,804
  • 6
  • 36
  • 42
Laurent
  • 14,122
  • 13
  • 57
  • 89
  • define your theme for edit text – Meenal Oct 26 '14 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. – Laurent Oct 26 '14 at 15:49
  • None of these answers are working for me on 4.3. Do you have a working solution? – Robert Baker Dec 15 '15 at 16:54
  • I had to extend `AppCompatEditText`, apparently. – EpicPandaForce Nov 28 '16 at 15:19

25 Answers25

486

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>
Laurent
  • 14,122
  • 13
  • 57
  • 89
  • 1
    What things will be affected by above changes ? Only TextViews or other views also. Please add a little more details – Shakti Malik Nov 20 '14 at 11:19
  • 9
    I see the color of the menu hamburger, back button, and scroll bar have changed to colorControlNormal. – ario Nov 21 '14 at 00:48
  • 1
    I've tried your solution it worked on design screen but not working when im running my app with real device and simulator. my edit text still black. – salih Feb 03 '15 at 10:00
  • 11
    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. – Emanuel Moecklin Feb 06 '15 at 18:59
  • 2
    I had a problem recently for pre-Lollipop versions. Creating a custom EditText loses these colors that you define in Styles XML from AppCompat Library. In order to keep these colors, take a look on @hordurh 's answer. And use it programmatically in your custom EditText's constructor. – osayilgan Feb 27 '15 at 01:37
  • 1
    Excellent answer but unfortunately it's not working for a theme where parent theme is @android:style/Theme.Holo.Light.NoActionBar. Any clue? – Suresh Sharma Apr 27 '15 at 10:45
  • 69
    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. – Alex Lockwood Apr 29 '15 at 21:50
  • 8
    Didn't work on Jelly Bean (4.2) but worked on Lollipop – Mangesh May 16 '15 at 09:12
  • 3
    The activity should inherit from `AppCompatActivity`. It will not work if it inherits from `Activity`. – Bharathwaaj Jan 12 '16 at 23:38
  • For some reason I had to use `android:colorControlNormal`, `android:colorControlActivated` and `android:colorControlHighlight` for it to work. – Ehsan Khaveh Apr 23 '20 at 10:20
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);
hordurh
  • 2,663
  • 1
  • 16
  • 19
  • 1
    But how can i reset to default background, i've got a lot of bugs after calling editText.getBackground().resetColorFilter() on Lollipop? – ultraon Jun 09 '15 at 13:49
  • Caution! adding this may cause to change color of editText across ALL app. Tested on Nexus 5. OS 6.0.1. – Alex Perevozchykov Feb 04 '16 at 17:10
  • 1
    @AlexPerevozchykov you might be right. Try adding .mutate() after .getBackground(). That should do it. – hordurh Feb 05 '16 at 10:40
  • @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 – Alex Perevozchykov Feb 05 '16 at 12:44
  • 1
    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? – Selin May 09 '16 at 08:56
  • @Selin checkout my solution and let me know whether it resolved your issue? – RQube Jun 29 '16 at 12:05
  • Thanks you so much bro :D I've spend a hour for find out this solution :D – Thân Hoàng Dec 15 '19 at 07:28
  • +1 for `mutate`, this is the way to go! I've tested multiple solutions (including `DrawableCompat.setTint`) but even though I saved the Background before changing it, resetting it back to the old one created a mix of both colors. Btw, `getColor` is deprecated since API 23, use `ContextCompat.getColor(context, R.color.your_color)` instead. – Neph Mar 10 '20 at 14:38
  • That was a fast edit. I'd recommend leaving the old version though and just editing in the new one with a note that it changed, basically a "<23" & ">=23" for people who still have/use an old project. ;) Btw, to reset call `editText.getBackground().setColorFilter(null)` (`editText.setBackgroundTintList(null)` doesn't work!), don't try saving the old Background and setting it back to it later, I tried to do that in multiple ways and failed every time because in the end the new color always comes back somehow. – Neph Mar 11 '20 at 11:24
147

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"/>
Community
  • 1
  • 1
reVerse
  • 35,075
  • 22
  • 89
  • 84
  • 1
    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. – reVerse May 30 '15 at 07:10
  • 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. – user2968401 May 31 '15 at 07:37
  • I am using `22.2.0` version of AppCompat but this trick is not working :( – Shajeel Afzal Jul 15 '15 at 21:04
  • 1
    using #000000 worked for me instead of colorControlNormal. – MikeOscarEcho Aug 20 '16 at 00:17
  • Perfect to change only one edit text in the app! (Exactly what I needed! Thanks) – Romain Barbier Jan 21 '20 at 17:34
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"
Moustafa EL-Saghier
  • 1,721
  • 1
  • 13
  • 43
l-l
  • 3,804
  • 6
  • 36
  • 42
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

Linh
  • 57,942
  • 23
  • 262
  • 279
  • @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 https://drive.google.com/file/d/0B_poNaia6t8kSzU3bDFVazRSSDA/view?usp=sharing. I don't know why this code not work for you so please let me know. thank you – Linh Feb 23 '17 at 01:45
  • @Renjith sorry for late response, please check my comment above – Linh Feb 23 '17 at 01:45
  • How do you reset the color to default with this code? – Neph Mar 10 '20 at 15:07
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

TanmayP
  • 706
  • 1
  • 6
  • 12
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);
    }
Felipe Conde
  • 2,024
  • 23
  • 26
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>

Ashwin H
  • 695
  • 7
  • 24
21

Use:

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

This will support pre-Lollipop devices not only +21

blueware
  • 5,205
  • 1
  • 40
  • 60
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.

Peter
  • 159
  • 7
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"/>
MinnuKaAnae
  • 1,646
  • 3
  • 23
  • 35
Pacific P. Regmi
  • 1,607
  • 19
  • 15
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);
}
ywwynm
  • 11,573
  • 7
  • 37
  • 53
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.

Mtl Dev
  • 1,604
  • 20
  • 29
  • 1
    This is changing whole background color, and we want to change only underline color. – Shahzain ali Jun 09 '16 at 02:17
  • @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) – nyconing Nov 21 '16 at 02:12
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.

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.

Sfseyhan
  • 1,321
  • 1
  • 13
  • 18
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);
}
Henrique de Sousa
  • 5,727
  • 49
  • 55
user2721167
  • 75
  • 1
  • 6
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);
RQube
  • 954
  • 3
  • 13
  • 28
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

Fraser
  • 15,275
  • 8
  • 53
  • 104
M.Zanella
  • 51
  • 1
  • 1
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.

Aleksandr Gorshkov
  • 473
  • 1
  • 6
  • 16
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.

mkasberg
  • 16,022
  • 3
  • 42
  • 46
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"/>
Oliver Dixon
  • 7,012
  • 5
  • 61
  • 95
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.

Community
  • 1
  • 1
Ankit Popli
  • 2,809
  • 3
  • 37
  • 61
  • And what method to use? setBackgroundTintList? It requires API 21. – CoolMind Feb 22 '17 at 13:02
  • [setSupportBackgroundTintList](https://developer.android.com/reference/android/support/v4/view/TintableBackgroundView.html#setSupportBackgroundTintList(android.content.res.ColorStateList)) for older API verisons. – Ankit Popli Feb 22 '17 at 13:07
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" />
jay patoliya
  • 611
  • 7
  • 8
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"/>
-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());
        }
}
Zain
  • 37,492
  • 7
  • 60
  • 84
Shahid Sarwar
  • 1,209
  • 14
  • 29