¿Cómo crear un botón de acción flotante (FAB) en Android, usando AppCompat v21?

79

Me gustaría crear un botón de acción flotante (para agregar elementos a una vista de lista), como el calendario de Google, manteniendo la compatibilidad con las versiones de Android anteriores a Lollipop (antes de la 5.0).

Creé este diseño:

Actividad main_activity.xml:

<LinearLayout ... >

     <include
         layout="@layout/toolbar"/>

     <RelativeLayout ... >

     <!-- My rest of the layout -->

          <!-- Floating action button -->
          <ImageButton style="@style/AppTheme"
                     android:layout_width="60dp"
                     android:layout_height="60dp"
                     android:text="New Button"
                     android:id="@+id/button"
                     android:src="@drawable/ic_fab"
                     android:background="@drawable/fab"
                     android:layout_alignParentBottom="true"
                     android:layout_alignParentRight="true"
                     android:layout_marginBottom="24dp"
                     android:layout_marginRight="24dp"/>

     </RelativeLayout>

 </LinearLayout>

Fab.xml dibujable:

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

Style styles.xml

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">#ff1d79b1</item>
        <item name="colorPrimaryDark">#ff084d95</item>
    </style>
</resources>

El resultado es similar, pero no existe el sombreado, una característica del diseño de materiales:

Botón de acción flotante del calendario:

Botón de acción flotante del calendario

Botón de acción flotante de mi aplicación:

Botón de acción flotante de mi aplicación

¿Cómo puedo agregar el sombreado a mi botón?

Ya usé el atributo elevación, pero no funciona

devpelux
fuente
1
La API de elevación es solo para Lollipop, ¿probaste un dispositivo Lollipop?
Marc Plano-Lesay
2
Probablemente sea hora de que aceptes una de las respuestas dadas.
Phantômaxx
De hecho, en mi 4.4.2 Samsung Galaxy S III, la sombra está ahí, gracias a AppCompat.
FractalBob

Respuestas:

100

Ya no es necesario crear su propia FAB ni utilizar una biblioteca de terceros, se incluyó en AppCompat 22.

https://developer.android.com/reference/android/support/design/widget/FloatingActionButton.html

Simplemente agregue la nueva biblioteca de soporte llamada diseño en su archivo gradle:

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

... y listo:

<android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_margin="16dp"
        android:clickable="true"
        android:src="@drawable/ic_happy_image" />
usuario1354603
fuente
1
¿Cómo se cambia el color de fondo?
Jjang
2
Por defecto, el color de fondo será el "colorAccent" de su tema. Sin embargo, también puedes usar floatingActionButton.setRippleColor (color), no dejes que el nombre 'ripple' te asuste, también funciona en dispositivos pre-lollipop.
user1354603
No tengo colorAccent, y si agrego uno y establezco el color en otra cosa, no funciona: el color se adhiere al verde / turquesa.
Jjang
Estaba usando un tercero para esto. Realmente me ayudó mucho. Gracias. Un problema con esto es que todavía se siente como si no estuviera completamente desarrollado.
V_J
1
@Jjang @ user1354603 de documentosThe background color of this view defaults to the your theme's colorAccent. If you wish to change this at runtime then you can do so via setBackgroundTintList(ColorStateList).
Muhammad Babar
43

Por lo general, he usado elementos de diseño xml para crear sombras / elevaciones en un widget previo a la piruleta. Aquí, por ejemplo, hay un dibujable xml que se puede usar en dispositivos pre-piruletas para simular la elevación del botón de acción flotante.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="8px">
    <layer-list>
        <item>
            <shape android:shape="oval">
                <solid android:color="#08000000"/>
                <padding
                    android:bottom="3px"
                    android:left="3px"
                    android:right="3px"
                    android:top="3px"
                    />
            </shape>
        </item>
        <item>
            <shape android:shape="oval">
                <solid android:color="#09000000"/>
                <padding
                    android:bottom="2px"
                    android:left="2px"
                    android:right="2px"
                    android:top="2px"
                    />
            </shape>
        </item>
        <item>
            <shape android:shape="oval">
                <solid android:color="#10000000"/>
                <padding
                    android:bottom="2px"
                    android:left="2px"
                    android:right="2px"
                    android:top="2px"
                    />
            </shape>
        </item>
        <item>
            <shape android:shape="oval">
                <solid android:color="#11000000"/>
                <padding
                    android:bottom="1px"
                    android:left="1px"
                    android:right="1px"
                    android:top="1px"
                    />
            </shape>
        </item>
        <item>
            <shape android:shape="oval">
                <solid android:color="#12000000"/>
                <padding
                    android:bottom="1px"
                    android:left="1px"
                    android:right="1px"
                    android:top="1px"
                    />
            </shape>
        </item>
        <item>
            <shape android:shape="oval">
                <solid android:color="#13000000"/>
                <padding
                    android:bottom="1px"
                    android:left="1px"
                    android:right="1px"
                    android:top="1px"
                    />
            </shape>
        </item>
        <item>
            <shape android:shape="oval">
                <solid android:color="#14000000"/>
                <padding
                    android:bottom="1px"
                    android:left="1px"
                    android:right="1px"
                    android:top="1px"
                    />
            </shape>
        </item>
        <item>
            <shape android:shape="oval">
                <solid android:color="#15000000"/>
                <padding
                    android:bottom="1px"
                    android:left="1px"
                    android:right="1px"
                    android:top="1px"
                    />
            </shape>
        </item>
        <item>
            <shape android:shape="oval">
                <solid android:color="#16000000"/>
                <padding
                    android:bottom="1px"
                    android:left="1px"
                    android:right="1px"
                    android:top="1px"
                    />
            </shape>
        </item>
        <item>
            <shape android:shape="oval">
                <solid android:color="#17000000"/>
                <padding
                    android:bottom="1px"
                    android:left="1px"
                    android:right="1px"
                    android:top="1px"
                    />
            </shape>
        </item>
    </layer-list>
</item>
<item>
    <shape android:shape="oval">
        <solid android:color="?attr/colorPrimary"/>
    </shape>
</item>
</layer-list>

En lugar de ?attr/colorPrimarypuede elegir cualquier color. Aquí hay una captura de pantalla del resultado:

ingrese la descripción de la imagen aquí

Justin Pollard
fuente
1
Gracias por compartir esto. Temía desenterrar el código XML nuevamente para volver a crear esto.
Cookster
Lo implementé hace un momento y es genial, solo hay una cosa extraña. Parece que cuando gira el teléfono, la sombra / elevación se pierde. ¿Alguna idea sobre eso? Gracias de antemano Justin
Amilcar Andrade
@AmilcarAndrade esa es una buena pregunta. Me he encontrado con cosas similares con otros elementos de diseño xml, pero en realidad estaba extrayendo un mapa de bits del propio elemento de diseño. Para resolver eso, esencialmente usé el dibujable como singleton; establecer una vez para que no se dibuje de nuevo. ¿Quizás pueda obtener el elemento dibujable como una variable estática y configurarlo como fondo en onCreate?
Justin Pollard
También agregué una mejora que puede agregar un efecto de riple realmente fácil, a continuación se muestra el código.
Amilcar Andrade
2
Para futuras referencias, este es un gran ejemplo para evitar las sombras y las elevaciones -> Curious-creature.com/2008/12/18/avoid-memory-leaks-on-android/…
Amilcar Andrade
4

El código xml de @Justin Pollard funciona muy bien. Como nota al margen, puede agregar un efecto dominó con las siguientes líneas xml.

    <item>
    <ripple
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?android:colorControlHighlight" >
        <item android:id="@android:id/mask">
            <shape android:shape="oval" >
                <solid android:color="#FFBB00" />
            </shape>
        </item>
        <item>
            <shape android:shape="oval" >
                <solid android:color="@color/ColorPrimary" />
            </shape>
        </item>
    </ripple>
</item>
Amilcar Andrade
fuente
2

Pruebe esta biblioteca , admite sombra, existe minSdkVersion=7y también admite android:elevationatributos API-21implícitamente.

La publicación original está aquí .

Oleksii K.
fuente
0

Agregue relleno y elevación:

 android:elevation="10dp"
 android:padding="10dp"
Simas
fuente