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.
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>
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);
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"/>
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"
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
}
J'espère que ça aide
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.
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);
}
Utilisation:
<EditText
app:backgroundTint="@color/blue"/>
Cela supportera les appareils pré-Lollipop non seulement +21
<!-- 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>
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.
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"/>
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.
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.
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);
}
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é.
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);
}
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);
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.
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"/>
Où BackgroundTint=color
pour la couleur désirée
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.
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"/>
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 .