Ejemplo de FloatingActionButton con biblioteca de soporte

129

Recientemente, leí estas publicaciones:

Biblioteca de soporte de diseño de Android

Biblioteca de soporte de Android, revisión 22.2.0

FlotanteAcciónBotón

Pero ninguno de ellos me da un ejemplo detallado sobre cómo crear uno nuevo FloatingActionButton. Tan difícil de entender, hago esta pregunta.

¿Alguien puede darme un ejemplo al respecto?

Cualquier ayuda será muy apreciada. Gracias por adelantado.

EDITAR

Acabo de encontrar algunos problemas en FloatingActionButton(FAB), y quiero mejorar otra respuesta. Vea mi respuesta a continuación.

Anggrayudi H
fuente

Respuestas:

274

Entonces, en su build.gradlearchivo, agregue esto:

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

Nota de AndroidX: Google está introduciendo nuevas bibliotecas de extensiones de AndroidX para reemplazar las bibliotecas de soporte más antiguas. Para utilizar AndroidX, primero asegúrese de que ha actualizado su gradle.propertiesarchivo , editado build.gradleal conjunto compileSdkVersionde 28(o superior), y utilice la siguiente línea en lugar del anterior compileuno.

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

A continuación, en su themes.xmlo styles.xmllo que sea, asegúrese de configurar esto, es el color de acento de su aplicación, y el color de su FAB a menos que lo anule (ver a continuación):

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

En el XML del diseño:

<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>

O si está utilizando la biblioteca de materiales de AndroidX anterior, en su lugar usaría esto:

<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>

Puede ver más opciones en los documentos ( documentos de material aquí) ( setRippleColor, etc.), pero uno de nota es:

    app:fabSize="mini"

Otro interesante: para cambiar el color de fondo de un solo FAB, agregue:

    app:backgroundTint="#FF0000"

(por ejemplo, para cambiarlo a rojo) al XML anterior.

De todos modos, en código, después de que la vista de Actividad / Fragmento se infla ...

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

Observaciones:

  • Si tiene uno de esos botones que está en una "costura" que divide dos vistas (usando un diseño relativo, por ejemplo) con, por ejemplo, un margen de diseño inferior negativo para superponer el borde, notará un problema: el tamaño de la FAB es en realidad muy diferente en lollipop vs. pre-lollipop. De hecho, puede ver esto en el editor de diseño visual de AS cuando cambia de una API a otra; de repente, se "hincha" cuando cambia a pre-lollipop. La razón del tamaño extra parece ser que la sombra expande el tamaño de la vista en todas las direcciones. Por lo tanto, debe tener esto en cuenta cuando ajuste los márgenes de la FAB si está cerca de otras cosas.
  • Aquí hay una manera de eliminar o cambiar el relleno si hay demasiado:

    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);
    }
    
  • Además, iba a colocar programáticamente la FAB en la "costura" entre dos áreas en un diseño relativo tomando la altura de la FAB, dividiéndola entre dos y utilizándola como compensación de margen. Pero myFab.getHeight () devolvió cero, incluso después de que la vista se infló, al parecer. En su lugar, utilicé un ViewTreeObserver para obtener la altura solo después de que se presentó y luego establecer la posición. Vea este consejo aquí . Se veía así:

        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);
                }
            });
        }
    

    No estoy seguro si esta es la forma correcta de hacerlo, pero parece funcionar.

  • Parece que puede reducir el espacio de sombra del botón disminuyendo la elevación.
  • Si desea el FAB en una "costura" puede usar layout_anchory layout_anchorGravityaquí hay un ejemplo:

    <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"/>
    

Recuerde que puede hacer que el botón salte del camino automáticamente cuando aparezca un Snackbar envolviéndolo en un CoordinatorLayout .

Más:

fattire
fuente
1
Por supuesto. Simplemente agregue, android:backgroundTint="#FF0000"por ejemplo, a FloatingActionBar en el XML. (agregando a la respuesta)
fattire
1
Hmm Está bien, lo cambiaré arriba entonces. ¡Gracias! Dark Leonhart: no he visto nada sobre el retorno rápido incorporado, pero hay ejemplos de hacerlo en otro lugar en stackoverflow que supongo que todavía funcionará. Además, hay algunas bibliotecas disponibles que también lo hacen.
fattire
1
Este componente, a partir de 22.2.0, en mi opinión, no está listo para la producción. Por cierto, puede ser un error tipográfico, pero no lo use spen la propiedad evelation. Debería serapp:elevation="4dp"
Joao Sousa
1
Tenga en cuenta que si está agregando un FloatingActionButtona a CoordinatorLayout, puede usar app:layout_anchor="element_with_seam"y app:layout_anchorGravity="bottom|right|end"colocar el FAB correctamente sobre una costura - vea el diseño de activity_detail de cheesesquare
ianhanniballake
2
@DarkLeonhart: mira mi ejemplo de mostrar / ocultar el FAB en el desplazamiento extendiendo su comportamiento.
ianhanniballake
49

Acabo de encontrar algunos problemas en FAB y quiero mejorar otra respuesta.


problema setRippleColor

Entonces, el problema vendrá una vez que establezca el color ondulado (color FAB al presionar) mediante programación setRippleColor. Pero, todavía tenemos una forma alternativa de configurarlo, es decir, llamando:

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

Su proyecto debe tener esta estructura:

/res/color/fab_ripple_color.xml

ingrese la descripción de la imagen aquí

Y el código de fab_ripple_color.xmles:

<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>

Finalmente, modifique su FAB ligeramente:

<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 -->

Para API nivel 21 y superior, establezca el margen derecho e inferior en 24dp:

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

Guías de diseño de FloatingActionButton

Como puede ver en mi código xml FAB anterior, configuré:

        ...
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        app:elevation="6dp"
        app:pressedTranslationZ="12dp"
        ...
  • Al establecer estos atributos, no es necesario establecerlos layout_marginTopy layout_marginRightnuevamente (solo en pre-Lollipop). Android lo colocará automáticamente en el lado derecho de la pantalla, lo mismo que FAB normal en Android Lollipop.

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

O puede usar esto en CoordinatorLayout:

        android:layout_gravity="end|bottom"
  • Necesitas tener 6dp elevationy 12dp pressedTranslationZ, de acuerdo con esta guía de Google.

Reglas de la FAB

Anggrayudi H
fuente
55
aprobado por la investigación involucrada. más 1 para el pressedTranslationZ. No lo sabia.
Joao Sousa
app: elevator = "6dp" app :pressedTranslationZ = "12dp" hace el truco para pre-lollipop, pero mi fab está literalmente en la esquina de la pantalla en Lollipop
Thiago
1
Está utilizando un valor incorrecto para "pressedTranslationZ ". No es el valor de elevación en estado presionado. PressedElevation = elevación + prensaTranslationZ. Entonces, los valores correctos son la aplicación: elevación = "6dp" aplicación: pressTranslationZ = "6dp"
e.shishkin
3
En realidad no necesita establecer los valores app:elevationy app:pressedTranslationZ. Su valor predeterminado es el definido en las pautas de diseño de materiales. De todos modos, e.shishkin tiene razón, los valores son app:elevation:6dpy pressedTranslationZ:6dp. Puede consultarlo en el código fuente
Christian García
12

FloatingActionButtonse extiende ImageView. Entonces, es simple como introducir un ImageViewen su diseño. Aquí hay una muestra 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" se agrega como una solución para problemas de elevación.

siriscac
fuente
4

para AndroidX use como

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

Si ya agregó todas las bibliotecas y todavía no funciona, use:

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

en vez de:

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

Y todo funcionará bien :)

Max Shwed
fuente