> Blog

nov 11, 2013 || por juan

ListActivity con Action Bar en Android

Para hacer una actividad que muestre una lista de elementos en Android lo más fácil es extender la clase ListActivity. Para hacer una actividad que utilice la barra de acciones o ActionBar, lo suyo es extender ActionBarActivity. ¿Y cuando queremos hacer las dos cosas a la vez?

En este post comentamso una fórmula sencilla para convertir una clase de tipo ListActivity en otra que, además de mostrar una lista de manera equivalente, utilice el ActionBar de Android.

En Android, la forma más sencilla se hacer una actividad que presente una lista de objetos pulsables es extender la clase ListActivity y asociarla a una vista con una estructura adecuada

Por otro lado, las últimas tendencias recomiendan que toda aplicación de Android utilice la barra de acciones o ActionBar, para lo cual típicamente las actividades deben extender la clase ActionBarActivity, normalmente desde la librería de compatibilidad (android.support.v7.app.ActionBarActivity).

El problema viene cuando tenemos una actividad de tipo ListActivity que no utiliza la barra de acciones y queremos hacer que sí la use. Tanto ActionBarActivity como ListActivity son clases abstractas y por lo tanto necesitan ser extendidas para utilizar las funcionalidades que nos ofrecen. No hay nada parecido a una ActionBarListActivity. Por tanto, como en java no existe la herencia múltiple, tenemos un problema si queremos extender las dos.

Por internet hay distintas alternativas, y probablemente la más popular sea extender la clase ActionBarActivity e implementar a mano las funciones de la clase ListActivity. 

No obstante, existe otra alternativa que a mi juicio es más sencilla. Si observamos la jerarquía de la clase ActionBarActivity veremos que es descendiente de android.support.v4.app.FragmentActivity. Es decir, una actividad de tipo ActionBarActivity también es FragmentActivity. Por otro lado, existe una clase que es a los fragmentos lo que ListActivity es a las actividades: ListFragment.

Sabiendo esto, una buena forma de obtener una actividad de tipo ActionBarActivity y al mismo tiempo que muestre cómodamente una lista es convertira en una FragmentActivity con un único fragmento de tipo ListFragment. Dada la dependencia entre las librerías de compatibilidad, teniendo en cuenta que ya teníamos que utilizar una  clase de la versión 7 de ésta, el hecho de utilizar otra de la versión 4 no empeora la retrocompatibilidad. Básicamente, se trata de convertir nuestra actividad en un fragmento, y crear una nueva actividad tonta para mostrarlo.

Para aclararlo un poco pongo a continuación la estructura de archivos que tendríamos que crear. Supongamos que partimos de una estructura sin action bar típica donde tenemos:

  • Una clase extendiendo ListActivity que contiene toda la lógica correspondiente al manejo de la lista y también la lógica de navegacióin (menús...).
  • Una vista que contiene el típico par ListView y TextView para mostrar el contenido de nuestra lista.

Para transformar esto en algo que utilice el ActionBar, sólo habría que hacer lo siguiente:

1. Crear una nueva clase extendiendo a ListFragment y trasladar a ella el código que tengamos en nuestra ListActivity correspondiente al manejo de la lista (adaptador, manejador de pulsaciones...). 
public class ItemListFragment extends ListFragment{
@Override
public void onActivityCreated(Bundle savedInstanceState) {
...
setListAdapter(adapter);
}
@Override 
public void onListItemClick(ListView l, View v, int position, long id) { ... }
...
}


2. Cambiar la herencia de nuestra actividad y hacer que extienda a android.support.v7.app.ActionBarActivity (y por lo tanto a FragmentActivity). En esta actividad se mantendría la lógica propia de navegación que ya tuviésemos. Por otro lado, en su método onCreate() se asociaría la vista definida en el punto 3.

public class ItemListFragmentActivity extends ActionBarActivity {
 
@Override
protected void onCreate(Bundle savedInstanceState{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list_fragment);
}
 
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.item_list_menu, menu);
return true;
}
 
@Override
public boolean onOptionsItemSelected(MenuItem item) { ... }
 
}
 

3. Crear una nueva vista para nuestra actividad conteniendo simplemente un fragmento para mostrar la lista de items. Por ejemplo:


<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ItemListFragmentActivity">
<fragment
android:id="@+id/itemListFragment" android:layout_width="match_parent" android:layout_height="match_parent" class="es.acore.example.ItemListFragment"/>
</RelativeLayout>

 


4. Con esto, ya tendriamos el trabajo hecho pero con una lista con la vista estandar. Para tener algo totalmente equivalente a lo que teníamos antes, tenemos que asociar la vista que teníamos en la versión sin action bar al fragmento. Para ello, simplemente hay que sobreescribir el método onCreateView() en la clase de nuestro fragmento para que devuelve la vista anterior, algo parecido a esto:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.item_list, container);
}

 

Con esta aproximación, ademas de utilizar el ActionBar, también hemos dado el primer paso para transformar nuestra aplicación en un diseño con fragmentos.

Más información:

Comenta
Título:
Nombre:
(obligatorio)
Email:
(no se publicará)
Comentario:
This is a captcha-picture. It is used to prevent mass-access by robots. (see: www.captcha.net)
 

Categorías

Últimas entradas

Página 1 de 3 > >>

dic 20, 2014 || Categoría:General
dic 9, 2013 || Categoría:android
nov 11, 2013 || Categoría:android