Exemple de FloatingActionButton avec Support Library

129

Récemment, j'ai lu ces articles:

Bibliothèque de support de conception Android

Bibliothèque de support Android, révision 22.2.0

FlottantActionButton

Mais aucun d'entre eux ne me donne un exemple détaillé sur la création d'un nouveau FloatingActionButton. Si difficile à comprendre, je pose cette question.

Quelqu'un peut-il m'en donner un exemple?

Toute aide sera appréciée. Merci d'avance.

ÉDITER

Je viens de trouver quelques problèmes sur FloatingActionButton(FAB), et je souhaite améliorer une autre réponse. Voir ma réponse ci-dessous.

Anggrayudi H
la source

Réponses:

274

Donc, dans votre build.gradlefichier, ajoutez ceci:

compile 'com.android.support:design:27.1.1'

Remarque AndroidX: Google introduit de nouvelles bibliothèques d'extensions AndroidX pour remplacer les anciennes bibliothèques de support. Pour utiliser AndroidX, assurez- vous d'gradle.properties abord que vous avez mis à jour votre fichier , modifié build.gradlepour définir compileSdkVersionsur 28(ou supérieur), et utilisez la ligne suivante au lieu de la précédente compile.

implementation 'com.google.android.material:material:1.0.0'

Ensuite, dans votre themes.xmlou styles.xmlou autre, assurez-vous de définir ceci - c'est la couleur d'accentuation de votre application - et la couleur de votre FAB, sauf si vous la remplacez (voir ci-dessous):

        <item name="colorAccent">@color/floating_action_button_color</item>

Dans le XML de la mise en page:

<RelativeLayout
 ...
 xmlns:app="http://schemas.android.com/apk/res-auto">

       <android.support.design.widget.FloatingActionButton
            android:id="@+id/myFAB"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_plus_sign"
            app:elevation="4dp"
            ... />

</RelativeLayout>

Ou si vous utilisez la bibliothèque de matériaux AndroidX ci-dessus, vous utiliserez plutôt ceci:

<RelativeLayout
 ...
 xmlns:app="http://schemas.android.com/apk/res-auto">

       <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/myFAB"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:srcCompat="@drawable/ic_plus_sign"
            app:elevation="4dp"
            ... />

</RelativeLayout>

Vous pouvez voir plus d'options dans les documents ( documents sur les matériaux ici) ( setRippleColor, etc.), mais l'une d'entre elles est:

    app:fabSize="mini"

Un autre intéressant - pour changer la couleur d'arrière-plan d'un seul FAB, ajoutez:

    app:backgroundTint="#FF0000"

(par exemple pour le changer en rouge) en XML ci-dessus.

Quoi qu'il en soit, dans le code, une fois que la vue de l'activité / du fragment est gonflée ...

    FloatingActionButton myFab = (FloatingActionButton)  myView.findViewById(R.id.myFAB);
    myFab.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            doMyThing();
        }
    });

Observations:

  • Si vous avez l'un de ces boutons sur une "couture" divisant deux vues (en utilisant un RelativeLayout, par exemple) avec, par exemple, une marge de mise en page inférieure négative pour chevaucher la bordure, vous remarquerez un problème: la taille du FAB est en fait très différent sur sucette vs pré-sucette. Vous pouvez en fait le voir dans l'éditeur de mise en page visuelle d'AS lorsque vous basculez entre les API - il "gonfle" soudainement lorsque vous passez à pré-sucette. La raison de la taille supplémentaire semble être que l'ombre agrandit la taille de la vue dans toutes les directions. Vous devez donc en tenir compte lorsque vous ajustez les marges du FAB si elles sont proches d'autres choses.
  • Voici un moyen de supprimer ou de modifier le rembourrage s'il y en a trop:

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) myFab.getLayoutParams();
        p.setMargins(0, 0, 0, 0); // get rid of margins since shadow area is now the margin
        myFab.setLayoutParams(p);
    }
  • En outre, j'allais placer le FAB par programme sur la "couture" entre deux zones dans un RelativeLayout en saisissant la hauteur du FAB, en divisant par deux et en l'utilisant comme décalage de marge. Mais myFab.getHeight () a renvoyé zéro, même après que la vue ait été gonflée, semblait-il. Au lieu de cela, j'ai utilisé un ViewTreeObserver pour obtenir la hauteur uniquement après avoir été disposé, puis défini la position. Consultez cette astuce ici . Cela ressemblait à ceci:

        ViewTreeObserver viewTreeObserver = closeButton.getViewTreeObserver();
        if (viewTreeObserver.isAlive()) {
            viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                        closeButton.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    } else {
                        closeButton.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    }
                    // not sure the above is equivalent, but that's beside the point for this example...
                    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) closeButton.getLayoutParams();
                    params.setMargins(0, 0, 16, -closeButton.getHeight() / 2); // (int left, int top, int right, int bottom)
                    closeButton.setLayoutParams(params);
                }
            });
        }

    Je ne sais pas si c'est la bonne façon de le faire, mais cela semble fonctionner.

  • Il semble que vous pouvez réduire l'espace d'ombre du bouton en diminuant l'élévation.
  • Si vous voulez le FAB sur une "couture", vous pouvez utiliser layout_anchoret layout_anchorGravityvoici un exemple:

    <android.support.design.widget.FloatingActionButton
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"
        android:src="@drawable/ic_discuss"
        android:layout_margin="@dimen/fab_margin"
        android:clickable="true"/>

N'oubliez pas que vous pouvez automatiquement faire sauter le bouton du chemin lorsqu'un Snackbar apparaît en l'enveloppant dans un CoordinatorLayout .

Plus:

grasse
la source
1
Sûr. Ajoutez simplement android:backgroundTint="#FF0000"par exemple à FloatingActionBar dans le XML. (ajoutant à la réponse)
fattire
1
Hmm. Ok, je vais le changer ci-dessus alors. Merci! Dark Leonhart - Je n'ai rien vu à propos du retour rapide intégré, mais il existe des exemples de le faire ailleurs sur stackoverflow qui, je suppose, fonctionneront toujours. De plus, certaines bibliothèques sont disponibles qui le font également.
fattire le
1
Ce composant, à partir de 22.2.0, à mon avis, n'est pas prêt pour la production. Btw, peut être une faute de frappe, mais ne l'utilisez pas spdans la propriété evelation. Ça devrait êtreapp:elevation="4dp"
Joao Sousa
1
Notez que si vous ajoutez a FloatingActionButtonà a CoordinatorLayout, vous pouvez utiliser app:layout_anchor="element_with_seam"et app:layout_anchorGravity="bottom|right|end"pour positionner correctement le FAB sur une couture - voir la mise en page activity_detail de cheesesquare
ianhanniballake
2
@DarkLeonhart - consultez mon exemple d'affichage / masquage du FAB lors du défilement en étendant son comportement.
ianhanniballake
49

Je viens de trouver quelques problèmes sur FAB et je veux améliorer une autre réponse.


Problème de setRippleColor

Ainsi, le problème surviendra une fois que vous aurez défini la couleur d'ondulation (couleur FAB sur pression) par programmation setRippleColor. Mais, nous avons encore une autre façon de le définir, c'est-à-dire en appelant:

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
ColorStateList rippleColor = ContextCompat.getColorStateList(context, R.color.fab_ripple_color);
fab.setBackgroundTintList(rippleColor);

Votre projet doit avoir cette structure:

/res/color/fab_ripple_color.xml

entrez la description de l'image ici

Et le code de fab_ripple_color.xmlest:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/fab_color_pressed" />
    <item android:state_focused="true" android:color="@color/fab_color_pressed" />
    <item android:color="@color/fab_color_normal"/>
</selector>

Enfin, modifiez légèrement votre FAB:

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_action_add"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    app:fabSize="normal"
    app:borderWidth="0dp"
    app:elevation="6dp"
    app:pressedTranslationZ="12dp"
    app:rippleColor="@android:color/transparent"/> <!-- set to transparent color -->

Pour le niveau d'API 21 et supérieur, définissez la marge droite et inférieure sur 24dp:

...
android:layout_marginRight="24dp"
android:layout_marginBottom="24dp" />

Guides de conception FloatingActionButton

Comme vous pouvez le voir sur mon code xml FAB ci-dessus, j'ai défini:

        ...
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        app:elevation="6dp"
        app:pressedTranslationZ="12dp"
        ...
  • En définissant ces attributs, vous n'avez pas besoin de définir layout_marginTopet à layout_marginRightnouveau (uniquement sur pré-Lollipop). Android le placera automatiquement sur le côté droit de l'écran, ce qui est identique au FAB normal dans Android Lollipop.

        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"

Ou, vous pouvez l'utiliser dans CoordinatorLayout:

        android:layout_gravity="end|bottom"
  • Vous devez avoir 6dp elevationet 12dp pressedTranslationZ, selon ce guide de Google.

Règles FAB

Anggrayudi H
la source
5
bravo pour la recherche impliquée. plus 1 pour le pressedTranslationZ. Je ne savais pas ça.
Joao Sousa le
app: elevation = "6dp" app: pressTranslationZ = "12dp" fait l'affaire pour pré-sucette, mais mon fab est littéralement dans le coin de l'écran sur Lollipop
Thiago
1
Vous utilisez une valeur incorrecte pour "presséTranslationZ". Ce n'est pas la valeur de l'élévation à l'état pressé. PressedElevation = élévation + presséTranslationZ. Les valeurs correctes sont donc app: elevation = "6dp" app: pressTranslationZ = "6dp"
e.shishkin
3
En fait, vous n'avez pas besoin de définir les valeurs app:elevationet app:pressedTranslationZ. Leur valeur par défaut est celle définie dans les directives de conception des matériaux. Quoi qu'il en soit, e.shishkin a raison, les valeurs sont app:elevation:6dpet pressedTranslationZ:6dp. Vous pouvez le vérifier dans le code source de
Christian García
12

FloatingActionButtons'étend ImageView. Donc, c'est simple comme introduire un ImageViewdans votre mise en page. Voici un exemple XML.

<android.support.design.widget.FloatingActionButton   xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/somedrawable"
    android:layout_gravity="right|bottom"
    app:borderWidth="0dp"
    app:rippleColor="#ffffff"/>

app:borderWidth="0dp" est ajouté comme solution de contournement pour les problèmes d'élévation.

siriscac
la source
4

pour AndroidX, utilisez comme

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/ic_add" />
Dan Alboteanu
la source
1

Si vous avez déjà ajouté toutes les bibliothèques et que cela ne fonctionne toujours pas, utilisez:

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/ic_add" 
/>

au lieu de:

<android.support.design.widget.FloatingActionButton
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   app:srcCompat="@drawable/ic_add"
 />

Et tout fonctionnera bien :)

Max Shwed
la source