ChatGPT解决这个技术问题 Extra ChatGPT

Changing EditText bottom line color with appcompat v7

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.

define your theme for edit text
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.
None of these answers are working for me on 4.3. Do you have a working solution?
I had to extend AppCompatEditText, apparently.

L
Laurent

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>

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.
h
hordurh

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);

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?
C
Community

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"/>

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 #000000 worked for me instead of colorControlNormal.
Perfect to change only one edit text in the app! (Exactly what I needed! Thanks)
M
Moustafa EL-Saghier

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"

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>"
L
Linh

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
}

https://i.stack.imgur.com/wu1yD.png

Hope it help


@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?
T
TanmayP

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


@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
F
Felipe Conde

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);
    }

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.
A
Ashwin H

<!-- 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>


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.
b
blueware

Use:

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

This will support pre-Lollipop devices not only +21


@powder366, can you post your app main theme?