web-dev-qa-db-fra.com

Changer la couleur de la ligne de fond de EditText avec appcompat v7

J'utilise appcompat v7 pour que l'apparence soit cohérente sur Android 5 et moins. Ça marche plutôt bien. Cependant, je ne peux pas comprendre comment changer la couleur de fond et la couleur d'accent pour EditTexts. C'est possible?

J'ai essayé de définir un Android:editTextStyle personnalisé (cf. ci-dessous), mais je n'ai réussi à changer que la couleur de fond ou la couleur du texte, mais pas la ligne de fond ni la couleur d'accent. Existe-t-il une valeur de propriété spécifique à utiliser? Dois-je utiliser une image pouvant être dessinée par le biais de la propriété Android:background? N'est-il pas possible de spécifier une couleur en 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>

Selon Android API 21 sources, les EditTexts avec un design matériel semblent utiliser colorControlActivated et colorControlNormal. Par conséquent, j'ai essayé de remplacer ces propriétés dans la définition de style précédente, mais cela n'a aucun effet. Probablement appcompat ne l'utilise pas. Malheureusement, je ne trouve pas les sources de la dernière version de appcompat avec la conception matérielle.

299
Laurent

Enfin, j'ai trouvé une solution. Cela consiste simplement à remplacer la valeur de colorControlActivated, colorControlHighlight et colorControlNormal dans la définition du thème de votre application et non dans votre style edittext. Pensez ensuite à utiliser ce thème pour l’activité de votre choix. Ci-dessous un exemple:

<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>
471
Laurent

Je sentais que cela nécessitait une réponse au cas où quelqu'un voudrait changer un seul edittext. Je le fais comme ça:

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

Bien que solution de Laurents soit correct, il présente certains inconvénients, décrits dans les commentaires, car non seulement la dernière ligne de la EditText est teintée mais le bouton Précédent de la Toolbar, CheckBoxes etc. aussi.

Heureusement, v22.1 sur appcompat-v7 a introduit de nouvelles possibilités. Il est maintenant possible d'attribuer un thème spécifique à une seule vue. Tout droit du Changelog :

Utilisation obsolète de app: theme for styling Toolbar. Vous pouvez maintenant utiliser Android: thème pour les barres d’outils sur tous les périphériques API de niveau 7 et supérieur et Android: thème support pour tous les widgets sur les périphériques de niveau 11 et supérieur d'API.

Ainsi, au lieu de définir la couleur souhaitée dans un thème global, nous en créons un nouveau et l’attribuons uniquement à la EditText.

Exemple:

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

Pour référence. Ceci peut être changé en xml en utilisant:

Android:backgroundTint="@color/blue"

Pour la compatibilité ascendante, utilisez:

app:backgroundTint="@color/blue"
94
l-l

Voici la solution pour API <21 et versions supérieures

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

J'espère que ça aide

45
Phan Van Linh

La réponse acceptée est un peu plus complexe, mais le plus efficace consiste à ajouter l'attribut colorAccent dans votre style AppTheme comme ceci:

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

L'attribut colorAccent est utilisé pour colorer les widgets dans l'application et doit donc être utilisé pour la cohérence.

34
TanmayP

Si vous utilisez appcompat-v7:22.1.0+, vous pouvez utiliser le DrawableCompat pour colorer vos 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);
    }
28
Felipe Conde

Utilisation:

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

Cela supportera les appareils pré-Lollipop non seulement +21

19
blueware
<!-- 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>
18
Ashwin H

Une solution rapide à votre problème consiste à rechercher dans votre application/build/intermediates/exploded-aar/com.Android.support/appcompat-v7/res/drawable/for abc_edit_text_material.xml et à copier ce fichier XML dans votre dossier pouvant être dessiné. Ensuite, vous pouvez changer la couleur des 9 fichiers de correctifs à l’intérieur de ce sélecteur, afin de correspondre à vos préférences.

12
Peter

Il est très facile d'ajouter simplement l'attribut Android:backgroundTint dans votre 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"/>
9

Moi aussi, je suis resté bloqué trop longtemps sur ce problème.

J'avais besoin d'une solution qui fonctionne pour les versions supérieures et inférieures à la v21.

J'ai finalement découvert une solution très simple, peut-être pas idéale mais efficace: Définissez simplement la couleur d'arrière-plan sur transparent dans les propriétés EditText.

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

J'espère que cela sauve du temps à quelqu'un.

8
Mtl Dev

Pour moi, j'ai modifié à la fois AppTheme et une valeur colors.xml ColorControlNormal et colorAccent m'ont aidé à changer la couleur de la bordure EditText. Ainsi que le curseur et le "|" quand à l'intérieur d'un 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>

Voici les couleurs.xml

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

J'ai sorti l'attribut Android: textCursorDrawable en @null que j'ai placé dans le style editText. Quand j'ai essayé d'utiliser ceci, les couleurs ne changeraient pas.

7

Voici une partie du code source de TextInputLayout dans la bibliothèque de conception de support ( MIS À JOUR pour la version 23.2.0 ) , qui change la couleur de la ligne du bas de EditText de manière plus 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));
    }
    ...
}

Il semble que tout le code ci-dessus devienne inutile en 23.2.0 si vous voulez changer la couleur par programmation.

Et si vous voulez supporter toutes les plateformes, voici ma méthode:

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

Vous pouvez définir l’arrière-plan d’edittext sur un rectangle avec un remplissage moins à gauche, à droite et en haut pour y parvenir. Voici l'exemple xml:

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

Remplacez la forme par un sélecteur si vous souhaitez fournir une largeur et une couleur différentes pour un edittext ciblé.

6
Sfseyhan

J'utilise cette méthode pour changer la couleur de la ligne avec PorterDuff, sans autre dessinable.

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

J'ai travaillé sur une solution de travail à ce problème après 2 jours de lutte, la solution ci-dessous est parfaite pour ceux qui veulent changer quelques textes d'édition, changer/changer de couleur avec le code Java, et veulent surmonter les problèmes de comportement différent sur les versions de système d'exploitation en raison de l'utilisation de la méthode 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();
    }
  }
}

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

Ajouter des lignes dans le 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>

Code Java pour changer de couleur

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

Si vous souhaitez modifier les résultats sans utiliser les couleurs de l'application, utilisez ces lignes dans votre thème:

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

Je ne connais pas d'autre solution.

4
rz0

Dans Activit.XML, ajoutez le 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"/>

BackgroundTint=color pour la couleur désirée

4
M.Zanella

J'ai été absolument dérouté par ce problème. J'avais tout essayé dans ce fil et dans d'autres, mais peu importe ce que j'ai fait, je ne pouvais pas changer la couleur du soulignement en autre chose que le bleu par défaut.

J'ai finalement compris ce qui se passait. J'utilisais (à tort) Android.widget.EditText lors de la création d'une nouvelle instance (mais le reste de mes composants provenait de la bibliothèque appcompat). J'aurais dû utiliser Android.support.v7.widget.AppCompatEditText. J'ai remplacé new EditText(this) par new AppCompatEditText(this) et le problème a été résolu instantanément. Il s'avère que si vous utilisez réellement AppCompatEditText, il ne fera que respecter le accentColor de votre thème (comme mentionné dans plusieurs commentaires ci-dessus) et aucune configuration supplémentaire n'est nécessaire.

2
mkasberg

C'est le plus simple et le plus efficace/réutilisable/fonctionne sur toutes les API
Créez une classe EditText personnalisée comme suit:

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

Ensuite, utilisez-le comme ceci:

 <company.com.app.EditText
        Android:layout_width="200dp"
        Android:layout_height="wrap_content"/>
2
Oliver Dixon

Pour changer l'arrière-plan EditText de manière dynamique, vous pouvez utiliser 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édits: Cette SO réponse à propos de ColorStateList est géniale .

1
Ankit Popli