web-dev-qa-db-fra.com

Effet de matière sur le bouton avec la couleur de fond

J'utilise la bibliothèque de support Android v21. 

J'ai créé un bouton avec une couleur d'arrière-plan personnalisée. Les effets de conception Matériau tels que l’ondulation, la révélation ont disparu (sauf l’altitude au clic) lorsque j’utilise la couleur de fond.

 <Button
 style="?android:attr/buttonStyleSmall"
 Android:background="?attr/colorPrimary"
 Android:textColor="@color/white"
 Android:textAllCaps="true"
 Android:layout_width="fill_parent"
 Android:layout_height="wrap_content"
 Android:text="Button1"
 />

Background Ce qui suit est un bouton normal et les effets fonctionnent très bien.

<Button
 style="?android:attr/buttonStyleSmall"
 Android:layout_width="fill_parent"
 Android:layout_height="wrap_content"
 Android:textAllCaps="true"
 Android:text="Button1"
/>

Default button

226
Sathesh

Lorsque vous utilisez Android:background, vous remplacez une grande partie du style et de l'aspect d'un bouton par une couleur vierge.

Mise à jour: Depuis la version version 23.0.0 de AppCompat , il existe un nouveau style Widget.AppCompat.Button.Colored qui utilise la variable colorButtonNormal de votre thème pour la couleur désactivée et colorAccent pour la couleur activée .

Cela vous permet de l'appliquer à votre bouton directement via

<Button
  ...
  style="@style/Widget.AppCompat.Button.Colored" />

Si vous avez besoin d'une colorButtonNormal ou colorAccent personnalisée, vous pouvez utiliser une ThemeOverlay comme expliqué dans this pro-tip et Android:theme sur le bouton.

Réponse précédente

Vous pouvez utiliser un dessin dans votre répertoire v21 pour votre arrière-plan, par exemple:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:color="?attr/colorControlHighlight">
    <item Android:drawable="?attr/colorPrimary"/>
</ripple>

Cela garantira que votre couleur d'arrière-plan est ?attr/colorPrimary et que l'animation d'ondulation par défaut utilise le ?attr/colorControlHighlight par défaut (que vous pouvez également définir dans votre thème si vous le souhaitez).

Remarque: vous devrez créer un sélecteur personnalisé pour une version inférieure à la v21:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:drawable="@color/primaryPressed" Android:state_pressed="true"/>
    <item Android:drawable="@color/primaryFocused" Android:state_focused="true"/>
    <item Android:drawable="@color/primary"/>
</selector>

En supposant que vous ayez certaines couleurs que vous souhaitez pour l'état par défaut, appuyé et focalisé. Personnellement, j'ai pris une capture d'écran d'une ondulation au milieu de la sélection et extrait l'état primaire/ciblé de celle-ci.

417
ianhanniballake

Il existe une autre solution simple consistant à créer un arrière-plan personnalisé pour les boutons "Plats" tout en conservant leurs effets "Matériel".

  1. Placez votre bouton dans ViewGroup avec l’arrière-plan souhaité défini
  2. set selectableItemBackground à partir du thème actuel en arrière-plan pour votre bouton (API> = 11)

c'est à dire. :

<FrameLayout
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:background="@color/blue">
    <Button
        style="?android:attr/buttonStyleSmall"
        Android:background="?android:attr/selectableItemBackground"
        Android:textColor="@Android:color/white"
        Android:textAllCaps="true"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:text="Button1"
        />
</FrameLayout>

Peut être utilisé pour les boutons Plat , cela fonctionne sur l'API> = 11, et vous obtiendrez un effet d'entraînement sur les appareils> = 21, en maintenant les boutons réguliers avant 21 ans jusqu'à ce que AppCompat soit mis à jour pour prendre en charge l'ondulation.

Vous pouvez également utiliser les boutons selectableItemBackgroundBorderless for> = 21 uniquement.

90
kiruwka

Voici un moyen simple et rétro-compatible de fournir un effet d’ondulation aux boutons en relief avec un arrière-plan personnalisé.

Votre mise en page devrait ressembler à ceci

<Button
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:background="@drawable/my_custom_background"
    Android:foreground="?android:attr/selectableItemBackground"/>
83
Bolein95

J'ai rencontré ce problème aujourd'hui en jouant avec la bibliothèque v22. 

En supposant que vous utilisez des styles, vous pouvez définir la propriété colorButtonNormal et les boutons utiliseront cette couleur par défaut. 

<style name="AppTheme" parent="BaseTheme">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/primaryColor</item>
    <item name="colorPrimaryDark">@color/primaryColorDark</item>
    <item name="colorAccent">@color/accentColor</item>
    <item name="colorButtonNormal">@color/primaryColor</item>
</style>

En dehors de cela, vous pouvez toujours créer un style pour le bouton, puis l'utiliser pour chaque bouton si vous aviez besoin d'un assortiment de couleurs (non testé, en spéculant).

N'oubliez pas d'ajouter Android: devant les noms des éléments dans votre style v21

25
Robert Rose

Avec AppCompat (22.1.1+), vous pouvez ajouter un style comme celui-ci:

<style name="MyGreenButton">
    <item name="colorButtonNormal">#009900</item>
</style>

Et utilisez-le simplement en appliquant le style:

<Android.support.v7.widget.AppCompatButton
    style="@style/MyGreenButton"
    Android:layout_width="match_width"
    Android:layout_height="wrap_content"
    Android:text="A Green Button"
    />

En changeant la couleur par programme, j’ai trouvé que le seul moyen de mettre à jour la couleur (sur les API 15 ou 16) consistait à utiliser la liste des teintes de fond. Et cela ne supprime pas l'animation radiale Nice sur les périphériques API 21:

ColorStateList colorStateList = new ColorStateList(new int[][] {{0}}, new int[] {0xFF009900}); // 0xAARRGGBB
button.setSupportBackgroundTintList(colorStateList);

Dans la mesure où button.setBackground(...) et button.getBackground().mutate().setColorFilter(...) ne modifie pas la couleur du bouton sur les API 15 et 16 comme sur l’API 21.

24
Robert

La réponse de @ ianhanniballake est absolument correcte et simple. Mais cela m'a pris quelques jours pour comprendre. Pour quelqu'un qui ne comprend pas sa réponse, voici une implémentation plus détaillée

<Button
        Android:id="@+id/btn"
        style="@style/MaterialButton"
        ... />


<style name="MaterialButton" parent="Widget.AppCompat.Button.Colored">
    <item name="Android:theme">@style/Theme.MaterialButton</item>
   ...
</style>


<style name="Theme.MaterialButton" parent="YourTheme">
    <item name="colorAccent">@color/yourAccentColor</item>
    <item name="colorButtonNormal">@color/yourButtonNormalColor</item>
</style>

=== Ou ===

<Button
        Android:id="@+id/btn"
        style="@style/Widget.AppCompat.Button.Colored"
        Android:theme="@style/Theme.MaterialButton" />

<style name="Theme.MaterialButton" parent="YourTheme">
    <item name="colorAccent">@color/yourAccentColor</item>
    <item name="colorButtonNormal">@color/yourButtonNormalColor</item>
</style>
20
Frank Nguyen

J'ai utilisé le backgroundTint et le premier plan:

<Button
    Android:layout_width="match_parent"
    Android:layout_height="40dp"
    Android:backgroundTint="@color/colorAccent"
    Android:foreground="?android:attr/selectableItemBackground"
    Android:textColor="@Android:color/white"
    Android:textSize="10sp"/>
13
SpyZip

Si vous êtes intéressé par ImageButton, vous pouvez essayer cette chose simple:

<ImageButton
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:src="@Android:drawable/ic_button"
    Android:background="?attr/selectableItemBackgroundBorderless"
/>
6
Ameer Khalifullah

Je suis venu à ce poste à la recherche d’un moyen d’avoir une couleur de fond de mon article ListView tout en conservant l’ondulation.

J'ai simplement ajouté ma couleur d'arrière-plan et le selectableItemBackground au premier plan:

<style name="my_list_item">
    <item name="Android:background">@color/white</item>
    <item name="Android:foreground">?attr/selectableItemBackground</item>
    <item name="Android:layout_height">@dimen/my_list_item_height</item>
</style>

et cela fonctionne comme un charme. Je suppose que la même technique pourrait également être utilisée pour les boutons. Bonne chance :)

6
Joakim

Utilisez backgroundTint au lieu de background

5
shem

v22.1 of appcompat-v7 a introduit de nouvelles possibilités. Il est maintenant possible d'assigner un thème spécifique à une seule vue.

Utilisation obsolète de app: theme for styling Toolbar. Vous pouvez maintenant utiliser Android: thème pour les barres d’outils sur tous les appareils de niveau API 7 et supérieur et Android: prise en charge des thèmes pour tous les widgets de l'API de niveau 11 ou supérieur dispositifs.

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 variable Button.

Exemple:

<style name="MyColorButton" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorButtonNormal">@color/myColor</item>
</style>

Et utilisez ce style comme thème de votre Button

<Button
 style="?android:attr/buttonStyleSmall"
 Android:layout_width="fill_parent"
 Android:layout_height="wrap_content"
 Android:text="Button1"
 Android:theme="@style/MyColorButton"/>
5
Bhargav Pandit

Si vous êtes prêt à utiliser une bibliothèque tierce, consultez traex/RippleEffect . Il vous permet d’ajouter un effet Ripple à la vue N&RSQUO;IMPORTE LAQUELLE avec seulement quelques lignes de code. Il vous suffit d’envelopper, dans votre fichier d’agencement XML, l’élément pour lequel vous souhaitez créer un effet d’ondulation avec un conteneur com.andexert.library.RippleView

En prime, il nécessite Min SDK 9 afin que vous puissiez avoir une conception cohérente à travers les versions de système d'exploitation.

Voici un exemple tiré du référentiel GitHub des bibliothèques:

<com.andexert.library.RippleView
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:rv_centered="true">

    <ImageView
        Android:layout_width="100dp"
        Android:layout_height="100dp"
        Android:src="@Android:drawable/ic_menu_edit"
        Android:background="@Android:color/holo_blue_dark"/> 

</com.andexert.library.RippleView>

Vous pouvez changer la couleur de l'ondulation en ajoutant cet attribut à l'élément RippleView: app:rv_color="@color/my_fancy_ripple_color

3
guy.gc
<Android.support.v7.widget.AppCompatButton
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:backgroundTint="#fff"
    Android:textColor="#000"
    Android:text="test"/>

Utilisation 

xmlns:app="http://schemas.Android.com/apk/res-auto"

et la couleur acceptera le pré-lolipop

3
André Bäuml

Alex Lockwood décrit deux approches dans l'excellent tutoriel: http://www.androiddesignpatterns.com/2016/08/coloring-buttons-with-themeoverlays-background-tints.html :

Approche n ° 1: Modification de la couleur d’arrière-plan du bouton avec un ThemeOverlay

<!-- res/values/themes.xml -->
<style name="RedButtonLightTheme" parent="ThemeOverlay.AppCompat.Light">
    <item name="colorAccent">@color/googred500</item>
</style>

<Button
    style="@style/Widget.AppCompat.Button.Colored"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:theme="@style/RedButtonLightTheme"/>

Approche n ° 2: Définition de la teinte de fond de AppCompatButton

<!-- res/color/btn_colored_background_tint.xml -->
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <!-- Disabled state. -->
    <item Android:state_enabled="false"
          Android:color="?attr/colorButtonNormal"
          Android:alpha="?android:attr/disabledAlpha"/>

    <!-- Enabled state. -->
    <item Android:color="?attr/colorAccent"/>

</selector>

<Android.support.v7.widget.AppCompatButton
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:backgroundTint="@color/btn_colored_background_tint"/>
2
makovkastar

Appliquer les couleurs par programme:

if (Android.os.Build.VERSION.SDK_INT >= Android.os.Build.VERSION_CODES.Lollipop) {

    ColorStateList colorStateListRipple = new ColorStateList(
            new int[][] {{0}},
            new int[] {Color.WHITE} // ripple color
            );

    RippleDrawable rippleDrawable = (RippleDrawable) myButton.getBackground();
    rippleDrawable.setColor(colorStateListRipple);
    myButton.setBackground(rippleDrawable); // applying the ripple color
}

ColorStateList colorStateList = new ColorStateList(
        new int[][]{
                new int[]{Android.R.attr.state_pressed}, // when pressed
                new int[]{Android.R.attr.state_enabled}, // normal state color
                new int[]{} // normal state color
        },
        new int[]{
                Color.CYAN, // when pressed
                Color.RED, // normal state color
                Color.RED // normal state color
        }
);

ViewCompat.setBackgroundTintList(myButton, colorStateList); // applying the state colors
0
Marlon