Comment créer une ondulation circulaire sur un bouton lorsque vous cliquez dessus?

122

Contexte

Sur l'application de numérotation d'Android, lorsque vous commencez à rechercher quelque chose et que vous cliquez sur le bouton fléché à gauche de EditText, vous obtenez un effet d'entraînement circulaire dessus:

entrez la description de l'image ici

Le problème

J'ai essayé de l'avoir aussi, mais j'en ai un rectangulaire:

    <ImageButton
        android:id="@+id/navButton"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="8dp"
        android:background="?android:attr/selectableItemBackground"
        android:src="@drawable/search_ic_back_arrow"/>

La question

Comment faire en sorte que le bouton ait un effet d'entraînement circulaire lorsqu'on clique dessus? Dois-je créer un nouveau dessinable, ou y a-t-il un moyen intégré pour cela?

développeur android
la source
2
github.com/traex/RippleEffect essayez ceci
rapide
réponse possible est ici stackoverflow.com/questions/33477025/…
Amrish Kakadiya
1
Envisagez de changer la réponse sélectionnée par celle avec le plus de votes positifs, car cela résout le problème
Jeff Barger
@JeffBarger Pourquoi? Les deux fonctionnent bien. Il n'y en a pas de meilleur entre eux.
développeur android le

Réponses:

18

Si vous avez déjà une image d'arrière-plan, voici un exemple d'ondulation qui ressemble à selectableItemBackgroundBorderless:

            <ImageButton
                android:id="@+id/btn_show_filter_dialog"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:background="@drawable/ic_filter_state"/>

ic_filter_state.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_pressed="true"
        android:state_enabled="true"
        android:drawable="@drawable/state_pressed_ripple"/>
    <item
        android:state_enabled="true"
        android:drawable="@drawable/ic_filter" />
</selector>

state_pressed_ripple.xml: (opacité définie à 10% sur fond blanc) 1AFFFFFF

 <?xml version="1.0" encoding="UTF-8"?>    
    <ripple xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape android:shape="oval">
                <solid android:color="#1AFFFFFF"/>
            </shape>
            <color android:color="#FFF"/>
        </item>
    </ripple>
l'amour en direct
la source
290

Si vous utilisez le thème AppCompat, vous pouvez définir l'arrière-plan de la vue comme suit:

android:background="?selectableItemBackgroundBorderless"

Cela ajoutera une ondulation circulaire sur 21 et au-dessus et un fond carré sur en dessous de 21.

liaison
la source
Agréable. Puis-je également définir la couleur de celui-ci d'une manière ou d'une autre?
développeur android
4
dans l'API 23, l'arrière-plan `` haut '' semble être la moitié de la taille par rapport à selectbleItemBackgroundBorderless
snodnipper
3
Belle, meilleure réponse. ty
Skywalker
1
@androiddeveloper, la couleur peut être définie en définissant colorControlHighlight comme ci-dessous dans votre styles.xml <item name = "colorControlHighlight"> # F00 </item>
bond
4
Si vous l'utilisez dans d'autres mises en page, vous devrez peut-être android:clipChildren="false"également permettre à l'animation de se propager.
Tanasis
83

Un autre attribut avec effet d'entraînement rond, spécialement pour la barre d'action:

android:background="?actionBarItemBackground"

UPD : la couleur d'ondulation peut être modifiée par cet attribut:

<!--somewhere in styles-->
<item name="colorControlHighlight">your_color_here</item>

Mais gardez à l'esprit que cet attribut s'applique à tous les effets d'entraînement par défaut.

Anrimien
la source
Un moyen de le personnaliser? Par exemple la couleur? Peut-être quelque chose dans les styles? Ou encore plus spécifiquement dans la balise XML de vue elle-même?
développeur android
Je ne sais pas, aujourd'hui j'ai résolu ce problème et les réponses ci-dessus n'ont pas fonctionné comme j'avais besoin. Je suppose que la couleur peut être personnalisée dans les styles, mais certainement pas dans la vue.
Anrimian
1
C'est exactement le bon effet que je recherche. Au fait, pouvez-vous mentionner où trouver cet attribut, il ne semble pas être documenté.
Jack Wang
2
Répond à la question OP. Doit être marqué comme meilleure réponse. +1
Corbella
2
@MeysamHadigheh ?est un raccourci pour?attr/
musooff
47

Créez et définissez une ondulation pouvant être dessinée comme arrière-plan. Quelque chose comme ça.

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/grey_15">
    <item android:id="@android:id/mask">
        <shape android:shape="oval">
            <solid android:color="?android:colorPrimary"/>
        </shape>
        <color android:color="@color/white"/>
    </item>
</ripple>
Thomas R.
la source
C'est quelque chose dans mon code. Vous pouvez utiliser vos couleurs :)
Thomas R.
Comment utiliser le sélecteur par défaut au cas où il serait pré-Lollipop? En outre, utilise-t-il les mêmes couleurs que celle du numéroteur?
développeur android
2
Vous pouvez mettre l'ondulation drawable dans votre dossier drawables-v21. Et pour pre L, utilisez un simple état dessinable. Utilisez le même nom de fichier et placez-le dans le dossier drawable (par défaut).
Thomas R.
2
Vous pouvez également créer un style. Dans le dossier values-v21, créez un nouveau style et définissez le dessin d'ondulation comme arrière-plan. Et pour pre L, c'est à dire dans votre dossier de valeurs styles.xml mettez en arrière-plan l'attribut "selectableItemBackground" pour le même style.
Thomas R.
1
Si vous voulez la même couleur d'ondulation que les autres effets d'ondulation par défaut utilisés dans l'application, utilisez "? Attr / colorControlHighlight" comme couleur.
alexbchr
27

Ajoutez simplement cet arrière-plan à votre vue

android:background=?android:attr/actionBarItemBackground

Dipakk Sharma
la source
19

Vous pouvez créer des ondulations de cercle pouvant être dessinées à l'aide de l' android:radiusattribut en XML.

Exemple:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="your_color"
    android:radius="your_radius" />

Faites attention, que votre your_radiusdoit être inférieure à la largeur et à la hauteur de votre vue. Par exemple: si vous avez une vue avec la taille 60dp x 60dp your_radiusdoit être proche 30dp(largeur / 2 ou hauteur / 2).

Travaillez sur Android 5.0 et supérieur.

Volodymyr Yatsykiv
la source
3

Si vous voulez des fichiers XML plus génériques, j'ai deux fichiers:

1) btn_ripple_background avec le code:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:state_pressed="true"
    android:state_enabled="true"
    android:drawable="@drawable/ripple_circular_shape"/>
</selector>

2) ripple_circuler_shape avec code:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/btn_state_pressed_text_color"
    android:shape="oval">
    <solid android:color="@color/btn_state_pressed_text_color" />
</shape>

enfin l'utilisation:android:foreground="@drawable/ripple_btn_background"

100RaBH
la source
2

Si vous voulez un effet d'entraînement qui ne traversera pas la limite du cercle, vous pouvez vérifier ce code. Cela fonctionne parfaitement pour moi. N'oubliez pas que vous devez donner id = @ android: id / mask dans ripple_blue.xml

<ImageButton
    android:id="@+id/send_password_to_mail_image_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_blue"
    android:src="@drawable/ic_filter" />

ripple_blue.xml

<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorRipple">

    <item android:id="@android:id/mask">

        <shape android:shape="oval">
            <solid android:color="@color/colorWindowBackground"/>
        </shape>

    </item>

    <item android:id="@android:id/background">

        <shape android:shape="oval">
            <solid android:color="@color/colorWindowBackground"/>
        </shape>

    </item>

</ripple>

color.xml

<resources xmlns:tools="http://schemas.android.com/tools">
    <color name="colorWindowBackground">#F2F5FC</color>
    <color name="colorRipple">#0288d1</color>
</resources>
Aminul Haque Aome
la source
1

Essayer:

android:background="@android:color/transparent"
android:clickable="true"
android:focusable="true"
android:foreground="?actionBarItemBackground"
duduCMT
la source
1
Veuillez ne pas publier uniquement le code comme réponse, mais inclure une explication de ce que fait votre code et de la manière dont il résout le problème de la question. Les réponses avec une explication sont généralement de meilleure qualité et sont plus susceptibles d'attirer des votes positifs.
Mark Rotteveel
Plus fluide que de définir actionBarItemBackground comme arrière-plan. Mais toujours pas exactement la même chose que l'animation de la barre d'action elle-même.
coolcool1994
1

ajoutez simplement cet article dans votre

           <ImageButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="?android:attr/actionBarItemBackground"
                app:srcCompat="@drawable/ic_arrow_drop_down_black_24dp" />
Ali Eslami
la source
1
Semble identique à ceci: stackoverflow.com/a/54440773/878126 .
développeur android
0

Dans Kotlin / Java, vous pouvez faire ce qui suit

fun View.applyCircularRippleEffect() {
    val backgroundResId = context.getResource(android.R.attr.actionBarItemBackground)

    if (backgroundResId != 0) {
        setBackgroundResource(backgroundResId)
        isClickable = true
        isFocusable = true
    }
}

// getResource extension
fun Context.getResource(resourceId: Int): Int {
    val out = TypedValue()
    theme.resolveAttribute(resourceId, out, true)

    return out.resourceId
}
mihails.kuzmins
la source
context.getResource
@RahulMandaliya merci pour le commentaire. Mon mauvais, c'était ma méthode d'extension personnalisée. Ajouté à la réponse
mihails.kuzmins