J'aimerais modifier légèrement la couleur d'un bouton standard Android afin de mieux l'adapter à l'image de marque d'un client.
Le meilleur moyen que j’ai trouvé de faire cela jusqu’à présent est de changer le tirage de Button
en tirable situé dans res/drawable/red_button.xml
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_pressed="true" Android:drawable="@drawable/red_button_pressed" />
<item Android:state_focused="true" Android:drawable="@drawable/red_button_focus" />
<item Android:drawable="@drawable/red_button_rest" />
</selector>
Mais pour cela, il faut que je crée trois tirables différents pour chaque bouton que je souhaite personnaliser (un pour le bouton au repos, un lorsque vous avez le focus et un lorsque vous appuyez dessus). Cela semble plus compliqué et non-sec que j'ai besoin.
Tout ce que je veux vraiment faire est d'appliquer une sorte de transformation de couleur au bouton. Y a-t-il un moyen plus facile de changer la couleur d'un bouton que je le fais?
J'ai découvert que tout cela peut être fait dans un seul fichier assez facilement. Mettez quelque chose comme le code suivant dans un fichier nommé custom_button.xml
puis définissez background="@drawable/custom_button"
dans votre affichage de bouton:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_pressed="true" >
<shape>
<gradient
Android:startColor="@color/yellow1"
Android:endColor="@color/yellow2"
Android:angle="270" />
<stroke
Android:width="3dp"
Android:color="@color/grey05" />
<corners
Android:radius="3dp" />
<padding
Android:left="10dp"
Android:top="10dp"
Android:right="10dp"
Android:bottom="10dp" />
</shape>
</item>
<item Android:state_focused="true" >
<shape>
<gradient
Android:endColor="@color/orange4"
Android:startColor="@color/orange5"
Android:angle="270" />
<stroke
Android:width="3dp"
Android:color="@color/grey05" />
<corners
Android:radius="3dp" />
<padding
Android:left="10dp"
Android:top="10dp"
Android:right="10dp"
Android:bottom="10dp" />
</shape>
</item>
<item>
<shape>
<gradient
Android:endColor="@color/blue2"
Android:startColor="@color/blue25"
Android:angle="270" />
<stroke
Android:width="3dp"
Android:color="@color/grey05" />
<corners
Android:radius="3dp" />
<padding
Android:left="10dp"
Android:top="10dp"
Android:right="10dp"
Android:bottom="10dp" />
</shape>
</item>
</selector>
Pour faire suite à la réponse de Tomasz, vous pouvez également définir par programmation la nuance de tout le bouton à l’aide du mode multiplicateur PorterDuff. Cela changera la couleur du bouton plutôt que la teinte.
Si vous commencez avec un bouton ombré gris standard:
button.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);
vous donnera un bouton ombré rouge,
button.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);
vous donnera un bouton ombré vert etc., où la première valeur est la couleur au format hexadécimal.
Cela fonctionne en multipliant la valeur de couleur du bouton actuel par votre valeur de couleur. Je suis sûr que vous pouvez faire beaucoup plus avec ces modes.
Mike, vous pourriez être intéressé par les filtres de couleur.
Un exemple:
button.getBackground().setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0xFFAA0000));
essayez ceci pour obtenir la couleur que vous voulez.
C’est ma solution qui fonctionne parfaitement à partir de l’API 15 . Cette solution conserve tous les effets de clic de bouton par défaut, tels que le matériau RippleEffect
. Je ne l'ai pas testé sur des API inférieures, mais cela devrait fonctionner.
Tout ce que vous devez faire, c'est:
1) Créez un style qui ne change que colorAccent
:
<style name="Facebook.Button" parent="ThemeOverlay.AppCompat">
<item name="colorAccent">@color/com_facebook_blue</item>
</style>
Je recommande d'utiliser
ThemeOverlay.AppCompat
ou votre principalAppTheme
comme parent pour conserver le reste de vos styles.
2) Ajoutez ces deux lignes à votre widget button
:
style="@style/Widget.AppCompat.Button.Colored"
Android:theme="@style/Facebook.Button"
Parfois, votre nouveau
colorAccent
n'apparaît pas dans Android Studio Preview, mais lorsque vous lancez votre application sur le téléphone, la couleur change.
<Button
Android:id="@+id/sign_in_with_facebook"
style="@style/Widget.AppCompat.Button.Colored"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:text="@string/sign_in_facebook"
Android:textColor="@Android:color/white"
Android:theme="@style/Facebook.Button" />
Vous pouvez maintenant également utiliser AppCompatButton de appcompat-v7 avec l'attribut backgroundTint
:
<Android.support.v7.widget.AppCompatButton
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
app:backgroundTint="#ffaa00"/>
J'aime la suggestion de filtre de couleur dans les réponses précédentes de @conjugatedirection et @Tomasz; Cependant, j’ai constaté que le code fourni jusqu’à présent n’était pas aussi facile à appliquer que prévu.
Premièrement, il n'a pas été mentionné où appliquer et effacer le filtre de couleur. Il est possible qu'il existe d'autres bons endroits pour le faire, mais ce qui m'est venu à l'esprit était un OnTouchListener .
D'après ma lecture de la question initiale, la solution idéale serait une solution sans images. La réponse acceptée en utilisant custom_button.xml de @emmby est probablement plus adaptée que les filtres de couleur si tel est votre objectif. Dans mon cas, je commence avec une image png d'un concepteur d'interface utilisateur indiquant à quoi le bouton est censé ressembler. Si je règle l'arrière-plan du bouton sur cette image, le retour d'informations par défaut est complètement perdu. Ce code remplace ce comportement par un effet d'assombrissement programmatique.
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 0x6D6D6D sets how much to darken - Tweak as desired
setColorFilter(v, 0x6D6D6D);
break;
// remove the filter when moving off the button
// the same way a selector implementation would
case MotionEvent.ACTION_MOVE:
Rect r = new Rect();
v.getLocalVisibleRect(r);
if (!r.contains((int) event.getX(), (int) event.getY())) {
setColorFilter(v, null);
}
break;
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
setColorFilter(v, null);
break;
}
return false;
}
private void setColorFilter(View v, Integer filter) {
if (filter == null) v.getBackground().clearColorFilter();
else {
// To lighten instead of darken, try this:
// LightingColorFilter lighten = new LightingColorFilter(0xFFFFFF, filter);
LightingColorFilter darken = new LightingColorFilter(filter, 0x000000);
v.getBackground().setColorFilter(darken);
}
// required on Android 2.3.7 for filter change to take effect (but not on 4.0.4)
v.getBackground().invalidateSelf();
}
});
J'ai extrait ceci en tant que classe distincte pour l'application à plusieurs boutons - indiqué comme classe interne anonyme juste pour comprendre l'idée.
Si vous créez des boutons de couleur avec XML, vous pouvez rendre le code un peu plus propre en spécifiant les états focalisé et enfoncé dans un fichier séparé et en les réutilisant. Mon bouton vert ressemble à ceci:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_focused="true" Android:drawable="@drawable/button_focused"/>
<item Android:state_pressed="true" Android:drawable="@drawable/button_pressed"/>
<item>
<shape>
<gradient Android:startColor="#ff00ff00" Android:endColor="#bb00ff00" Android:angle="270" />
<stroke Android:width="1dp" Android:color="#bb00ff00" />
<corners Android:radius="3dp" />
<padding Android:left="10dp" Android:top="10dp" Android:right="10dp" Android:bottom="10dp" />
</shape>
</item>
</selector>
La solution la plus courte qui fonctionne avec toutes les versions de Android:
<Button
app:backgroundTint="@color/my_color"
Notes/Conditions requises :
app:
espace de nom et pas le Android:
espace de nom!appcompat version> 24.2.0
dépendances {compile 'com.Android.support:appcompat-v7:25.3.1'}
J'utilise cette approche
style.xml
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="Android:colorPrimaryDark">#413152</item>
<item name="Android:colorPrimary">#534364</item>
<item name="Android:colorAccent">#534364</item>
<item name="Android:buttonStyle">@style/MyButtonStyle</item>
</style>
<style name="MyButtonStyle" parent="Widget.AppCompat.Button.Colored">
<item name="Android:colorButtonNormal">#534364</item>
<item name="Android:textColor">#ffffff</item>
</style>
Comme vous pouvez le voir ci-dessus, j'utilise un style personnalisé pour mon bouton. La couleur du bouton correspond à la couleur d'accent. Je trouve que cette approche est bien meilleure que de définir Android:background
, car je ne perdrai pas l'effet d'entraînement que Google fournit.
Utilisez-le de cette façon:
buttonOBJ.getBackground().setColorFilter(Color.parseColor("#YOUR_HEX_COLOR_CODE"), PorterDuff.Mode.MULTIPLY);
Il existe maintenant un moyen beaucoup plus simple: Android-holo-colors.com
Il vous permettra de changer facilement les couleurs de tous les éléments dessinables holo (boutons, fileuses, ...). Vous sélectionnez la couleur, puis vous téléchargez un fichier Zip contenant des éléments dessinables pour toutes les résolutions.
Dans <Button>
, utilisez Android:background="#33b5e5"
. ou mieux Android:background="@color/navig_button"
Vous pouvez également utiliser cet outil en ligne pour personnaliser votre bouton http://angrytools.com/Android/button/ et utiliser Android:background="@drawable/custom_btn"
pour définir le bouton personnalisé dans votre présentation.
La bibliothèque de composants DroidUX possède un widget ColorButton
dont la couleur peut être facilement modifiée, à la fois via la définition xml et par programmation au moment de l'exécution, de sorte que vous pouvez même laisser l'utilisateur définir le bouton couleur/thème si votre application le permet.
Vous pouvez définir le thème de votre bouton à cette
<style name="AppTheme.ButtonBlue" parent="Widget.AppCompat.Button.Colored">
<item name="colorButtonNormal">@color/HEXColor</item>
<item name="Android:textColor">@color/HEXColor</item>
</style>
Une méthode simple consiste à définir une classe de boutons personnalisée qui accepte toutes les propriétés souhaitées, telles que le rayon, le dégradé, la couleur pressée, la couleur normale, etc. Un échantillon est ici
Ceci est extrêmement utile si vous avez beaucoup de boutons avec les mêmes propriétés comme le rayon, la couleur sélectionnée, etc. Vous pouvez personnaliser votre bouton hérité pour gérer ces propriétés supplémentaires.
Résultat (aucun sélecteur d'arrière-plan n'a été utilisé).
Bouton normal
Bouton appuyé
Selon les directives de conception du matériau, vous devez utiliser le style ci-dessous, code
<style name="MyButton" parent="Theme.AppCompat.Light>
<item name="colorControlHighlight">#F36F21</item>
<item name="colorControlHighlight">#FF8D00</item>
</style>
et dans la mise en page ajouter cette propriété à votre bouton
Android:theme="@style/MyButton"
C'est simple .. ajoutez cette dépendance dans votre projet et créez un bouton avec 1. N'importe quelle forme 2. N'importe quelle couleur 3. N'importe quelle bordure 4. Avec des effets importants
https://github.com/manojbhadane/QButton
<com.manojbhadane.QButton
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="OK"
app:qb_backgroundColor="@color/green"
app:qb_radius="100"
app:qb_strokeColor="@color/darkGreen"
app:qb_strokeWidth="5" />
Pour créer un bouton de style différent qui fonctionne assez bien, je sous-classe l'objet Button et applique un filtre de couleur. Cela gère également les états activés et désactivés en appliquant une alpha au bouton.
import Android.annotation.TargetApi;
import Android.content.Context;
import Android.graphics.Color;
import Android.graphics.ColorFilter;
import Android.graphics.LightingColorFilter;
import Android.graphics.drawable.Drawable;
import Android.graphics.drawable.LayerDrawable;
import Android.os.Build;
import Android.util.AttributeSet;
import Android.widget.Button;
public class DimmableButton extends Button {
public DimmableButton(Context context) {
super(context);
}
public DimmableButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DimmableButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@SuppressWarnings("deprecation")
@Override
public void setBackgroundDrawable(Drawable d) {
// Replace the original background drawable (e.g. image) with a LayerDrawable that
// contains the original drawable.
DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d);
super.setBackgroundDrawable(layer);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void setBackground(Drawable d) {
// Replace the original background drawable (e.g. image) with a LayerDrawable that
// contains the original drawable.
DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d);
super.setBackground(layer);
}
/**
* The stateful LayerDrawable used by this button.
*/
protected class DimmableButtonBackgroundDrawable extends LayerDrawable {
// The color filter to apply when the button is pressed
protected ColorFilter _pressedFilter = new LightingColorFilter(Color.LTGRAY, 1);
// Alpha value when the button is disabled
protected int _disabledAlpha = 100;
// Alpha value when the button is enabled
protected int _fullAlpha = 255;
public DimmableButtonBackgroundDrawable(Drawable d) {
super(new Drawable[] { d });
}
@Override
protected boolean onStateChange(int[] states) {
boolean enabled = false;
boolean pressed = false;
for (int state : states) {
if (state == Android.R.attr.state_enabled)
enabled = true;
else if (state == Android.R.attr.state_pressed)
pressed = true;
}
mutate();
if (enabled && pressed) {
setColorFilter(_pressedFilter);
} else if (!enabled) {
setColorFilter(null);
setAlpha(_disabledAlpha);
} else {
setColorFilter(null);
setAlpha(_fullAlpha);
}
invalidateSelf();
return super.onStateChange(states);
}
@Override
public boolean isStateful() {
return true;
}
}
}
valeurs\styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="RedAccentButton" parent="ThemeOverlay.AppCompat.Light">
<item name="colorAccent">#ff0000</item>
</style>
ensuite:
<Button
style="@style/Widget.AppCompat.Button.Colored"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="text" />
<Button
style="@style/Widget.AppCompat.Button.Colored"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:enabled="false"
Android:text="text" />
<Button
style="@style/Widget.AppCompat.Button.Colored"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="text"
Android:theme="@style/RedAccentButton" />
<Button
style="@style/Widget.AppCompat.Button.Colored"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:enabled="false"
Android:text="text"
Android:theme="@style/RedAccentButton" />