Lollipop new features: Floating Action Button

jueves, 4 de junio de 2015


Vamos a continuar con las nuevas características que aparecieron en Lollipop con la aparición de Matrial Design, ya van unos cuantos artículos. En este artículo vamos a ver el Float Action Button, al que llamaremos FAB a partir de ahora.

Introducción a Floating Action Button

Según las epecificaciones de Material Design, FAB es un tipo de botón cuyo objetivo es recomendar la acción principal de una pantalla, pero no todas las pantallas tienen que tener un FAB. Es un botón que se situa elevado por encima del layout de la ventana y se visualiza de forma clara.

Solo debe existir un FAB por pantalla que representa la acción principal.

Debe representar una acción positiva como añadir, enviar mensaje, no negativas como borrar o de menor importancia como copiar, cortar etc..

Personalmente me esperaba por parte de Google darnos el trabajo más hecho porque para ser una especificación suya para crear un FAB y además compatible con versiones anteriores requieres de varios pasos manuales y bastante repetitivos entre apps, de ahí que hayan surgido en GitHub librerías que proporcionan botón FAB ya creado y compatible con versiones anteriores.

Parece que esta pega la han solucionado en la siguente versión con una librería anunciada en el pasado I/O, donde ya tendremos un widget FloatActionButton.

Ejemplo

Vamos a añadir un botón FAB en la ventana detalle de item de la aplicación que estamos creando, voy a explicar como hacerlo de forma manual, alguna carácteristica habitual de un FAB voy a renunciar a ella para versiones anteriores porque requiere de más pasos manuales y creo que hay que buscar un equilibrio y prefiero prescinfdir de que algo se vea exactamente como en Lollipop en versiones anteriores y que el código quede más limpio y más compacto.

El FAB que voy a crer en la ventana de detalle va a representar la acción de ver la imagen a pantalla completa.

En el layout del fragement de los datos añadimos un image button que será nuestro FAB.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    .
    .
    .

    <ImageButton
        android:id="@+id/detailItemfab"
        android:layout_width="@dimen/fab_size"
        android:layout_height="@dimen/fab_size"
        android:src="@drawable/fullscreen"
        android:background="@drawable/fab_background"
        android:elevation="4dp"
        android:stateListAnimator="@anim/fab_animation"
        android:layout_gravity="center"
        />

     .
     .
     .
</LinearLayout>


Las propiedades android:elevation="4dp" y android:stateListAnimator="@anim/fab_animation" solo se van a ejecutar si la versión Android del dispositivo es API 21 o superior.

Como background creamos fab_background.xml en la carpeta drawable, se compone de un shape ovalado y le ponemos un color por defecto.

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@android:color/holo_red_light"/>
</shape>


Ahora creamos una carpeta anim con el sufijo de versión 21, de forma que solo aplica en versión 21 o superior. Dentro creamos el fichero de animación fab_animation.xml para realizar una traslacion en el eje z y así dar la sesación de presionar el botón.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <set>
            <objectAnimator
                android:propertyName="translationZ"
                android:duration="100"
                android:valueFrom="1"
                android:valueTo="6"
                android:valueType="floatType"/>
        </set>
    </item>
    <item>
        <set>
            <objectAnimator
                android:propertyName="translationZ"
                android:duration="100"
                android:valueFrom="6"
                android:valueTo="1"
                android:valueType="floatType"/>
        </set>
    </item>
</selector>


Vamos a tener un nuevo activity donde vamos a tener la imagen a pantalla completa, este activity va a contener el fragment de la iamgen del item.

Entonces ahora solo nos falta abrir el activity de pantalla completa cuando se pulsa sobre el FAB.

Definimos un interface y un listener en el fragment donde se encuentra el FAB para notificar al activity del item detail que se quiere abrir el activity de pantalla completa. Invocaremos el método del listenr cuando se pulse el FAB.

public class ItemDataFragment extends Fragment {
    .
    .
    .

    private OpenItemFullScreenListener openItemFullScreenListener;

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {


        View rootView = inflater.inflate(R.layout.fragment_item_data, container, false);

        detailItemfab =(ImageButton)rootView.findViewById(R.id.detailItemfab);

        //Click fullscreen
        detailItemfab.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View view) {
                if (openItemFullScreenListener != null)
                    openItemFullScreenListener.openItemFullScreen(item);
            }
        });

        return rootView;
    }

    .
    .
    .

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if (activity instanceof OpenItemFullScreenListener) {
            openItemFullScreenListener = (OpenItemFullScreenListener) activity;
        }
    }

    public static interface OpenItemFullScreenListener {
        public void openItemFullScreen(Item item);
    }
}


En el item detail activity, que a su vez esta haciendo de OpenItemFullScreenListener, abrimos el activity de la imagen a pantalla completa utilizando la transición de elemento compartido.

  public class ItemDetailActivity  extends ActionBarActivity
                                 implements ItemImageFragment.OnPaletteGeneratedListener,
                                            ItemDataFragment.OpenItemFullScreenListener{

    .
    .
    .

    @Override
    public void openItemFullScreen(Item item) {
        View sharedView = findViewById(R.id.detailItemImage);
        String transitionName = getString(R.string.image_transition_name);

        ActivityOptionsCompat options =
                ActivityOptionsCompat.makeSceneTransitionAnimation(
                        this,  sharedView, transitionName);

        Intent intent = new Intent(this, ItemFullScreenActivity.class);
        intent.putExtra("item", item);
        ActivityCompat.startActivity(this, intent, options.toBundle());
    }
}

Concusiones

El Float Action Button es un botón que representa la acción principal de la pantalla, su implementación requiere de varios pasos manuales. Esto es algo que parece que va a mejorar en la próxima versión donde tendremos un widget FloatActionButton que implementará toda la funcionalidad.

Código fuente en GitHub - tag 0.5

Libros relacionados

Android Programming: The Big Nerd Ranch Guide.
Android Programming In a Day!: The Power Guide for Beginners In Android App Programming

No hay comentarios:

Publicar un comentario