Cambiar el color de la línea inferior de EditText con appcompat v7

Estoy usando appcompat v7 para obtener el aspecto consistente en Android 5 y menos. Funciona bastante bien Sin embargo, no puedo entender cómo cambiar el color de la línea inferior y el color de acento para EditTexts. ¿Es posible?

He intentado definir un android:editTextStyle personalizado android:editTextStyle (ver abajo) pero solo tuve éxito al cambiar el color de fondo completo o el color del texto, pero no la línea inferior ni el color de acento. ¿Hay un valor de propiedad específico para usar? ¿Tengo que usar una imagen dibujable personalizada a través de la propiedad android:background ? ¿no es posible especificar un color en hexa?

   @style/Widget.App.EditText   ???  

De acuerdo con las fonts de android API 21, los EditTexts con diseño de material parecen usar colorControlActivated y colorControlNormal . Por lo tanto, he intentado anular estas propiedades en la definición de estilo anterior, pero no tiene ningún efecto. Probablemente appcompat no lo use. Lamentablemente, no puedo encontrar las fonts para la última versión de appcompat con diseño de material.

Finalmente, he encontrado una solución. Simplemente consiste en anular el valor de colorControlActivated , colorControlHighlight y colorControlNormal en la definición del tema de su aplicación y no su estilo de texto de edición. Luego, piense en usar este tema para cualquier actividad que desee. A continuación hay un ejemplo:

  

Sentí que esto necesitaba una respuesta en caso de que alguien quisiera cambiar solo un texto de edición. Lo hago así:

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

Si bien la solución de Laurents es correcta, presenta algunos inconvenientes, como se describe en los comentarios, ya que no solo se EditText la línea inferior de EditText sino también el botón Atrás de la Toolbar de Toolbar , CheckBoxes , etc.

Afortunadamente v22.1 de appcompat-v7 introdujo algunas nuevas posibilidades. Ahora es posible asignar un tema específico solo a una vista. Directamente desde el registro de cambios :

Uso obsoleto de la aplicación: tema para diseñar la barra de herramientas. Ahora puede usar android: theme para barras de herramientas en todos los niveles de API 7 y dispositivos superiores y android: compatibilidad con temas para todos los widgets en API de nivel 11 y dispositivos superiores.

Entonces, en lugar de establecer el color deseado en un tema global, creamos uno nuevo y lo asignamos solo a EditText .

Ejemplo:

  

  

Para referencia. Esto se puede cambiar en xml usando:

 android:backgroundTint="@color/blue" 

Aquí está la solución para API <21 y superior

 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

Espero que ayude

La respuesta aceptada es algo más por estilo, pero lo más eficiente es agregar el atributo colorAccent en su estilo de AppTheme de la siguiente manera:

   

El atributo colorAccent se usa para el tinte de widgets en toda la aplicación y, por lo tanto, se debe usar para coherencia.

Si está utilizando appcompat-v7:22.1.0+ puede usar DrawableCompat para teñir sus 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); } 

Utilizar:

  

Esto admitirá dispositivos pre-Lollipop no solo +21

   

Una solución rápida para su problema es mirar en yourappspackage / build / intermedios / exploded-aar / com.android.support / appcompat-v7 / res / drawable / para abc_edit_text_material.xml y copiar ese archivo xml en su carpeta dibujable. Luego puede cambiar el color de los 9 archivos de parche desde el interior de este selector, para que coincida con sus preferencias.

Aquí hay una parte del código fuente de TextInputLayout en la biblioteca de diseño de soporte ( ACTUALIZADO para la versión 23.2.0 ), que cambia el color de la línea inferior de EditText una manera más simple:

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

Parece que todo el código anterior se vuelve inútil en este momento en 23.2.0 si desea cambiar el color programáticamente.

Y si quieres soportar todas las plataformas, aquí está mi método:

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

Yo también estuve atascado en este problema por mucho tiempo.

Necesité una solución que funcionara para las versiones tanto por encima como por debajo de v21.

Finalmente descubrí una solución muy simple, quizás no ideal pero efectiva: simplemente establezca el color de fondo como transparent en las propiedades de EditText.

  

Espero que esto le ahorre a alguien algo de tiempo.

Para mí modifiqué tanto el AppTheme como el valor colors.xml. Tanto el colorControlNormal como el colorAccent me ayudaron a cambiar el color del borde EditText. Además del cursor, y el “|” cuando dentro de un EditText.

  

Aquí está el colors.xml

 < ?xml version="1.0" encoding="utf-8"?>  #B7EC2A  

Saqué el atributo android: textCursorDrawable a @null que coloqué dentro del estilo editText. Cuando traté de usar esto, los colores no cambiarían.

Puede establecer el fondo de edittext en un rectángulo con menos relleno a la izquierda, derecha y arriba para lograrlo. Aquí está el ejemplo xml:

        

Reemplace la forma con un selector si desea proporcionar diferentes anchos y colores para el texto de edición enfocado.

Utilizo este método para cambiar el color de la línea con PorterDuff, sin otro dibujar.

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

Es muy fácil solo agrega android:backgroundTint atributo android:backgroundTint en tu EditText .

 android:backgroundTint="@color/blue" android:backgroundTint="#ffffff" android:backgroundTint="@color/red"  

Si desea cambiar los resultados finales sin utilizar los colores de la aplicación, use estas líneas en su tema:

 @android:style/Widget.EditText @android:style/Widget.EditText 

No sé otra solución.

En Activit.XML agregue el código

  

Donde BackgroundTint=color para el color deseado

Resolví una solución de trabajo para este problema después de 2 días de lucha, la solución de abajo es perfecta para aquellos que quieren cambiar solo un poco de texto de edición, cambiar / cambiar de color a través de código Java y quieren superar los problemas de comportamiento diferente en las versiones del sistema operativo debido al uso del método setColorFilter ()

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

Usos en xml

  

Agregue líneas con estilo

  

código java para alternar color

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

Estaba absolutamente desconcertado por este problema. Había intentado todo en este hilo, y en otros, pero no importaba lo que hiciera, no podía cambiar el color del subrayado a otra cosa que no fuera el azul predeterminado.

Finalmente descubrí lo que estaba pasando. Estaba (incorrectamente) usando android.widget.EditText al hacer una nueva instancia (pero el rest de mis componentes eran de la biblioteca appcompat). Debería haber usado android.support.v7.widget.AppCompatEditText . new EditText(this) con el new AppCompatEditText(this) y el problema se solucionó al instante. Resulta que si realmente está usando AppCompatEditText , solo respetará el accentColor de su tema (como se menciona en varios comentarios más arriba) y no es necesaria ninguna configuración adicional.

Este es el más fácil y eficiente / reutilizable / funciona en todas las API
Cree una clase de EditText personalizada como esta:

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

Entonces úsalo así:

   

Para cambiar dinámicamente el fondo EditText, puede usar 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); 

Créditos: Esta respuesta SO sobre ColorStateList es increíble .

Por favor, modifique este método según su necesidad. ¡Esto funcionó para mí!

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