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