Introducción
En el siguiente post expondremos como hemos añadido a nuestra aplicación varias animaciones para cuando el usuario realiza el gesto "swipe" sobre un elemento de una lista para que se visualice la acción asociada a ese gesto mientras se realiza el mismo.
Una de los principales puntos de un diseño centrado en el usuario es que la interfaz sea agradable y fluida. Por ejemplo si desarrollamos una aplicación para la lectura de documentos el cambio de página no se limite simplemente a dejar de mostrar la pagina actual y mostrar la siguiente, sino que cuando el usuario deslice el dedo por la pantalla se realice una animación de transición del cambio de página entre la nueva y la actual y produzca el efecto visual de leer un libro real.
Android nos proporciona diferentes animaciones para esta transiciones intermedias y en nuestro caso la que nos interesaba era la animación "Screen Slider" de tal forma que cuando el usuario deslice el dedo sobre un elemento de una lista se produzcan acciones diferentes para ese elemento y además la vista del elemento cambie conforme se mueve el dedo para mostrar la acción que se va a realizar. En nuestro caso las acciones serían las siguientes:
- Si se desliza de izquierda a derecha el elemento se actualiza.
- Si se desliza de derecha a izquierda el elemento queda seleccionado para después poder borrarse.
Sin embargo esta animación que nos proporciona Android tiene una pega y es que por defecto una vez que se detecta el gesto, la animación se reproduce de principio a fin y no tenemos la posibilidad de ajustarla al movimiento del dedo de tal forma que si el usuario inicia el gesto y de repente decide cancelar la acción no habría posibilidad de parar y volver atrás en la animación.
Una posible solución a este problema sería el de definir la animación paso a paso para tener un mayor control sobre ella. Sin embargo este trabajo nos lo podemos ahorrar gracias a la amplia comunidad de Android y concretamente al grupo "47deg". Este grupo no da la solución y nos proporciona una biblioteca para realizar dos tipos de animaciones para cuando el usuario realiza el gesto "Swipe" sobre un elemento de una lista. Una aplicación de ejemplo para comprender mejor esto la puedes encontrar en su cuenta "gitHub" en la siguiente dirección:
- https://github.com/47deg/android-swipelistview-sample
Instalación
En nuestro caso no pudimos utilizar la herramienta "gradle" para generar el jar de la biblioteca así que para poder integrar la biblioteca a nuestro proyecto lo que hemos hecho a sido integrar el código de la biblioteca en nuestro proyecto: concretamente introduciendo el paquete "fortysevendeg" en nuestro proyecto.
Para resolver las dependencias necesarias para esta biblioteca nos bajamos la ultima versión de la biblioteca "nineoldandroids" y la integramos en nuestro proyecto. La podéis encontrar en la siguiente cuenta de gitHub:
- https://github.com/JakeWharton/NineOldAndroids/
SWIPE LIST VIEW Library
Antes de pasar a utilizar la biblioteca explicaremos brevemente el contenido de la misma:
- SwipeListView: esta clase define un listView con la posibilidad de
visualizar la animación al realizar el gesto swipe sobre un elemento de
la lista. La clase define cuatro modos para activar o desactivar las
diferentes animaciones:
- SWIPE_MODE_RIGHT: activar solo la animación de transición de izquierda a derecha.
- SWIPE_MODE_LEFT: activar solo la animación de transición de derecha a izquierda.
- SWIPE_MODE_BOTH: activar ambas animaciones
- SWIPE_MODE_NONE: no se activa ninguna.
El atributo "swipeMode" lo podemos cambiar mediante la siguiente función pasándole alguno de los diferentes modos:
setSwipeMode(int modoNuevo)
-
BaseSwipeListViewListener: esta clase "abstracta" implementa la
interfaz SwipeListViewListener la cual define las diferentes acciones
que podemos realizar cuando se produce un cambio en un elemento de la
lista: por ejemplo podemos realizar un acción concreta cuando la
animación finaliza. La ventaja de utilizar esta clase y no implementar
directamente la interfaz es que podemos sobreescribir solo los métodos
que queramos usar.
Utilización de la biblioteca
Ahora veremos como utilizar esta biblioteca y como dar solución a nuestro problema de la forma más fácil:
Lo primero que debemos hacer es crearnos el layout para nuestro elemento de la lista el cual deberá estar formado por dos capas. En nuestro caso son las siguientes:
- La capa delantera compuesta de varias etiquetas de organizadas en un linearLayout.
- Y la capa trasera compuesta por una sola etiqueta correspondiente a la acción de "editar".
La estructura del layout sería la siguiente (se he omitido los atributos no relevantes para este caso):
<FrameLayout
...
>
<LinearLayout
android:id = "@+id/back"
android:tag="back"
...
>
<TextView ... >
</LinearLayout>
<LinearLayout
android:id = "@+id/front"
android:tag = "front"
...
>
<TextView ... >
</LinearLayout>
</FrameLayout>
Y definir el layout para nuestra lista de elementos del tipo SwipeListView:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.fortysevendeg.swipelistview.SwipeListView
xmlns:swipe="http://schemas.android.com/apk/res-auto"
android:id="@id/android:list"
android:listSelector="#00000000"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
swipe:swipeFrontView="@+id/front"
swipe:swipeBackView="@+id/back"
swipe:swipeCloseAllItemsWhenMoveList="true"
swipe:swipeMode="both"/>
<!-- swipe:swipeDrawableChecked="@drawable/choice_selected" swipe:swipeDrawableUnchecked="@drawable/choice_unselected" -->
</LinearLayout>
Pues bien ya solo nos queda utilizar la biblioteca para crearnos nuestro listView animado.
public class ExamListFragment extends ListFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
ExamListListener examListener;
SwipeListView swipeListView = (SwipeListView) getListView();
swipeListView.setSwipeActionLeft(SwipeListView.SWIPE_ACTION_CHOICE);
swipeListView.setSwipeOpenOnLongPress(false);
examListener = new ExamListListener(this, swipeListView, actionListener);
swipeListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
swipeListView.setMultiChoiceModeListener(examListener);
swipeListView.setSwipeListViewListener(examListener);
swipeListView.setOnItemClickListener(examListener);
}
public static class ExamListListener extends BaseSwipeListViewListener implements AbsListView.MultiChoiceModeListener{
@Override
public void onOpened(int position, boolean toRight) {
// Aqui se llama cuando la animación de abrir termina
}
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
mode.setTitle("Selecionado/s (" + swipeListView.getCountSelected() + ")");
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
// ...
return true
default:
return false;
}
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.main_context, menu);
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
swipeListView.unselectedChoiceStates();
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
}
}
Lo primero que hacemos es obtener el ListView de nuestra lista que será una instancia de la clase SwipeListView. Una vez obtenida la instancia establecemos la acción de dejar seleccionado el elemento cuando se produzca un "swipe" de derecha a izquierda y quitamos la acción correspondiente al "long click" ya que por defecto este gesto tiene asignada la acción de abrir el elemento. Después creamos una instancia del objeto ExamListListener el cual será el encargado de recibir todos los eventos producidos sobre los elementos de la lista y realizar las acciones oportunas.
No hay comentarios:
Publicar un comentario