Ajouter un effet d'entraînement à mon bouton avec la couleur d'arrière-plan du bouton?

128

J'ai créé un bouton et je veux ajouter un effet d'entraînement à ce bouton!

J'ai créé un fichier XML bouton bg: (bg_btn.xml)

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:startColor="#FFFFFF" android:endColor="#00FF00" android:angle="270" />
<corners android:radius="3dp" />
<stroke android:width="5px" android:color="#000000" />
</shape>

Et voici mon fichier d'effet d'entraînement: (ripple_bg.xml)

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

Et c'est mon bouton auquel je veux ajouter un effet d'entraînement:

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:layout_centerHorizontal="true"
android:layout_marginTop="173dp"
android:textColor="#fff"
android:background="@drawable/ripple_bg"
android:clickable="true" />

Mais après l'ajout de l'effet d'entraînement, l'arrière-plan du bouton est transparent et le bouton s'affiche uniquement lorsque vous cliquez dessus, comme ceci:

Avant de cliquer

Sur clic

Mais j'ai besoin à la fois de la couleur d'arrière-plan du bouton et de l'effet d'entraînement, j'ai trouvé une partie de ce code dans différents blogs de Stack Overflow, mais cela ne fonctionne toujours pas!

rakcode
la source
veuillez faire des captures d'écran beaucoup plus petites la prochaine fois .. (redimensionner avant le téléchargement)
user25
@ user25, vous pouvez également simplement ajouter un lou mau lien de l'image. (voir mon montage)
Suragch

Réponses:

156

Voici un autre xml dessinable pour ceux qui veulent ajouter tous ensemble un arrière-plan dégradé, un rayon de coin et un effet d'entraînement:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorPrimaryDark">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorPrimaryLight"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>
</ripple>

Ajoutez ceci à l'arrière-plan de votre bouton.

<Button
    ...
    android:background="@drawable/button_background" />

PS: cette réponse fonctionne pour Android api 21 et supérieur.

Pei
la source
4
@pei Comment obtenez-vous ces infos? Je veux dire comment vous savez qu'il existe un élément XML appelé ripple pour faire ce travail?
1
C'est l'un des concepts utilisés dans la conception de matériaux. Veuillez commencer à taper une nouvelle balise racine dans un xml dessinable dans Android Studio, vous devriez alors pouvoir voir toutes les balises disponibles, y compris ripple.
Pei
1
à quoi sert l'élément masque?
Prashant
10
cela nécessite le niveau d'API 21
M.kazem Akhgary
2
cela fonctionne mais comment cela fonctionne n'est pas expliqué. il doit être lié à l'identifiant de l'élément. Doit être référencé.
oiyio
156

Ajoutez le "?attr/selectableItemBackground"à l' android:foregroundattribut de votre vue s'il a déjà un arrière-plan avec android:clickable="true".

barre oblique inverseN
la source
ne fonctionne pas toujours, mais vous pouvez ajouter un arrière-plan à l'effet d'entraînement comme indiqué dans les commentaires de la réponse acceptée
Tyler
J'ai dû utiliser cette solution car j'ai utilisé un arrière-plan personnalisé pour mon bouton. Cela a très bien fonctionné.
bnayagrawal le
@ROAR, c'est vrai, mais au moins: "Ce n'est pas une erreur; l'application ignorera simplement l'attribut. Cependant, si l'attribut est important pour l'apparence ou la fonctionnalité de votre application, vous devriez envisager de trouver un autre moyen le même résultat avec uniquement les attributs disponibles, puis vous pouvez éventuellement créer une copie de la mise en page dans un dossier layout-vNN qui sera utilisé sur l'API NN ou une version ultérieure où vous pourrez profiter du nouvel attribut. " Donc, cela fonctionne bien sur les appareils au-dessus de l'API 23 et est ignoré lorsque ci-dessous (nous pouvons juste tools:ignore="UnusedAttribute).
JorgeAmVF
sans bibliothèque de support Android, ce serait ?android:attr/selectableItemBackground( android:attrau lieu de attr)
Week
1
android:foregroundl'attribut n'a pas d'effet sur les niveaux d'API inférieurs à 23
Vadim Kotov
67

Ajouter un effet d'entraînement / une animation à un bouton Android

Remplacez simplement votre attribut de fond de bouton par android: background = "? Attr / selectableItemBackground" et votre code ressemble à ceci.

      <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/selectableItemBackground"
        android:text="New Button" />

Une autre façon d'ajouter un effet d'entraînement / une animation à un bouton Android

En utilisant cette méthode, vous pouvez personnaliser la couleur de l'effet d'entraînement. Tout d'abord, vous devez créer un fichier xml dans votre répertoire de ressources dessinables. Créez un fichier ripple_effect.xml et ajoutez le code suivant. res / drawable / ripple_effect.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

Et définir l'arrière-plan du bouton sur le fichier de ressources dessinable ci-dessus

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_effect"
    android:padding="16dp"
    android:text="New Button" />
Jigar Patel
la source
1
Pour moi, l'effet d'entraînement n'est pas apparu. c'était juste un commutateur de couleur pour le bouton: / Ma version Android est 5.1.1 donc cela devrait fonctionner. Pourriez-vous aider? J'ai suivi tes pas
UrviG
android: la couleur doit être différente de celle du mât android: couleur, ou vous voulez voir l'effet d'entraînement
SpyZip
2
si vous voulez un arrière-plan, vous ajoutez simplement un autre élément à l'ondulation, comme: <item android: drawable = "? attr / colorPrimary" />
Tyler
36

En plus de la solution de Jigar Patel , ajoutez ceci au ripple.xml pour éviter le fond transparent des boutons.

<item
    android:id="@android:id/background"
    android:drawable="@color/your-color" />

XML complet :

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/your-color"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/your-color" />
        </shape>
    </item>
    <item
        android:id="@android:id/background"
        android:drawable="@color/your-color" />
</ripple>

Utilisez ce ripple.xml comme arrière-plan de votre bouton:

android:background="@drawable/ripple"
Sudheesh R
la source
2
Nous n'avons pas eu besoin d'utiliser le <item android:id="@android:id/mask"> [...]. Sauf si vous voulez un masque ovale. Merci pour votre réponse!
Filipe Brito
Que fait ce <item android: id = "@ android: id / mask"> de toute façon, j'ai créé 2 éléments similaires avec et sans cet attribut, et ils se ressemblent exactement
Sartheris Stormhammer
@SartherisStormhammer à partir de la documentation officielle: si un calque de masque est défini, l'effet d'entraînement sera masqué contre ce calque avant d'être dessiné sur le composite des calques enfants restants. Si aucun calque de masque n'est défini, l'effet d'entraînement est masqué par rapport au composite des calques enfants. C'est le lien, developer.android.com/reference/android/graphics/drawable/…
Sudheesh R
@SudheeshR qui rend les choses encore plus déroutantes
Sartheris Stormhammer
@SartherisStormhammer D'après cette documentation officielle, je pense que c'est assez clair. L'effet d'ondulation se dessine sur les calques enfants / masqués. Veuillez relire le document, vous comprendrez.
Sudheesh R
33

Lorsque le bouton a un arrière-plan du dessinable, nous pouvons ajouter un effet d'entraînement au paramètre de premier plan. Vérifiez ci-dessous le code qu'il fonctionne pour mon bouton avec un arrière-plan différent

    <Button
    android:layout_width="wrap_content"
    android:layout_height="40dp"
    android:gravity="center"
    android:layout_centerHorizontal="true"                                                             
    android:background="@drawable/shape_login_button"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:text="@string/action_button_login"
     />

Ajouter ci-dessous le paramètre pour l'effet d'entraînement

   android:foreground="?attr/selectableItemBackgroundBorderless"
   android:clickable="true"

Pour référence, reportez-vous au lien ci-dessous https://jascode.wordpress.com/2017/11/11/how-to-add-ripple-effect-to-an-android-app/

Jasmine John
la source
2
Attribut android: le premier plan n'a aucun effet sur les niveaux d'API inférieurs à 23
Ali Khaki
1
Un inconvénient de cette approche est que, même si mon fond de bouton était ovale, l'ondulation s'est propagée jusqu'aux bords rectangulaires.
iCantC
14

AppCompat v7 +

Si vous ne préfixez pas avec ?android:votre application, cela plantera.

Vous devez utiliser "?android:attr/selectableItemBackground"ou "?android:attr/selectableItemBackgroundBorderless", en fonction de vos préférences. Je préfère Borderless.

Vous pouvez le mettre dans android:backgroundou android:foregroundpour conserver les propriétés existantes.

L'élément doit avoir android:clickable="true"et android:focusable="true"pour que cela fonctionne, mais de nombreux éléments, tels que les boutons, les ont truepar défaut.

<Button
    ...
    android:background="@color/white"
    android:foreground="?android:attr/selectableItemBackgroundBorderless"
/>
<TextView
    ...
    android:background="?android:attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:focusable="true"
/>

Programmation (Java)

TypedValue value = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
myView.setBackgroundResource(value.resourceId);
myView.setFocusable(true); // If needed for view type

Programmation (Kotlin)

val value = TypedValue()
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
myView.setBackgroundResource(value.resourceId)
myView.setFocusable(true) // If needed for view type

Fonction d'extension Kotlin réutilisable

myView.ripple()

fun View.ripple(): View {
    val value = TypedValue()
    context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
    setBackgroundResource(value.resourceId)
    isFocusable = true // Required for some view types
    return this
}
Gibolt
la source
7

L'ajout d'attributs de premier plan et cliquables a fonctionné pour moi.

<Button
    ... 
    android:background="@color/your_color"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true" />
Ashwin
la source
6

En plus de Sudheesh R

Ajouter un effet d'entraînement / animation à un bouton Android avec une forme de rectangle de bouton avec un coin

Créer un fichier xml res / drawable / your_file_name.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/colorWhite"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="50dp" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorAccent"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="50dp" />
        </shape>
    </item>
</ripple>
Digvijay Machale
la source
4

Lorsque vous utilisez android: background, vous remplacez une grande partie du style et de l'apparence d'un bouton par une couleur vide.

Mise à jour: À partir de la version 23.0.0 d'AppCompat, il existe un nouveau style Widget.AppCompat.Button.A coloré qui utilise le colorButtonNormal de votre thème pour la couleur désactivée et colorAccent pour la couleur activée.

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

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

Vous pouvez utiliser un dessinable dans votre répertoire v21 pour votre arrière-plan tel que:

<?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 est utilisée en utilisant la valeur par défaut? Attr / colorControlHighlight (que vous pouvez également définir dans votre thème si vous le souhaitez).

Remarque: vous devrez créer un sélecteur personnalisé pour moins de 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>
Atman Bhatt
la source
im using minSDK lvl 21
rakcode
il n'y a pas de dossier dessinable v21, un seul dossier ce dossier lui-même dossier v21
rakcode
oui, j'ai aussi utilisé cette API, si j'utilise cette API après avoir cliqué sur mon application
plante
en fait, je teste mon application sur mon téléphone avec le mode débogage et mon système d'exploitation est CyanogenMod13 (Android 6, Marshmellow)
rakcode
4

essaye ça

<Button
            android:id="@+id/btn_location"
            android:layout_width="121dp"
            android:layout_height="38dp"
            android:layout_gravity="center"
            android:layout_marginBottom="24dp"
            android:layout_marginTop="24dp"
            android:foreground="?attr/selectableItemBackgroundBorderless"
            android:clickable="true"
            android:background="@drawable/btn_corner"
            android:gravity="center_vertical|center_horizontal"
            android:paddingLeft="13dp"
            android:paddingRight="13dp"
            android:text="Save"
            android:textColor="@color/color_white" />
Raveendra
la source
4

Une approche simple consiste à définir un thème de vue comme indiqué ici .

some_view.xml

<ImageView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:background="?attr/selectableItemBackgroundBorderless"
   android:focusable="true"
   android:src="@drawable/up_arrow"
   android:theme="@style/SomeButtonTheme"/>

some_style.xml

<style name="SomeButtonTheme" >
   <item name="colorControlHighlight">@color/someColor</item>
</style>
Adam Hurwitz
la source
3

Utilisez simplement:

android:backgroundTint="#f816a463"

Au lieu de:

android:background="#f816a463"

Ne pas oublier de changer Buttondeandroid.support.v7.widget.AppCompatButton

Gilad Shapira
la source
1
Le problème est que si vous avez besoin d'un bouton pour remplir à 100% l'écran horizontal, vous ne le ferez pas.
Filipe Brito
1

Une solution alternative à l'utilisation de la <ripple>balise (que je préfère personnellement ne pas faire, car les couleurs ne sont pas "par défaut"), est la suivante:

Créez un dessin pour l'arrière-plan du bouton et incluez-le <item android:drawable="?attr/selectableItemBackground">dans le<layer-list>

Ensuite (et je pense que c'est la partie importante) définie par programme backgroundResource(R.drawable.custom_button)sur votre instance de bouton.

Activité / Fragment

Button btn_temp = view.findViewById(R.id.btn_temp);
btn_temp.setBackgroundResource(R.drawable.custom_button);

Disposition

<Button
    android:id="@+id/btn_temp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/custom_button"
    android:text="Test" />

custom_button.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white" />
            <corners android:radius="10dp" />
        </shape>
    </item>
    <item android:drawable="?attr/selectableItemBackground" />
</layer-list>
Aidan hôte
la source
Pourquoi définir à nouveau backgroundResource par programmation, alors que layout xml définit l'arrière-plan de Button?
SunnyShiny9