Patrón de diseño: Navigation Drawer
Aunque este patrón está presente desde hace mucho tiempo en muchas aplicaciones Android e incluso en las propias de Google, hasta ahora, era necesario utilizar librerías de terceras partes para poderle implementar. El problema con el uso de estas diferentes librerías, es que cada una aportaba una funcionalidad y aspecto diferente.
Ahora, ya es posible, encontrarnos con el patrón en las guías de diseño además de haber liberado una actualización en su librería de soporte, de forma, que todos los desarrolladores puedan utilizar este patrón de la misma forma.
El action bar, se ha usado para temas de navegación, ahora ya con el nuevo patrón, tenemos que tener en cuenta que el action bar sólo es para las acciones y el navigation drawer para la navegación.
¿Qué es el Navigation Drawer?
Seguro que lo habéis visto en muchas aplicaciones. Es un panel que se desplaza desde el borde de la parte derecha y que visualiza las principales opciones de navigación de la aplicación. Cuando desplazamos el navigation drawer, le superponemos sobre el contenido de la pantalla, pero no sobre el action bar. Sin embargo, el action bar modifica su contenido, pues elimina todas las opciones que tuviese la vista y las sobreescribe por el icono y el nombre de la aplicación. Sólo se mantiene el menú de desbordamiento con los elementos para las accione estandar para la parametrización y la ayuda.
Para ocultar el menú, el usuario tiene cuatro opcioes:
- Tocar contenido fuera del navigation drawer.
- Deslizar a la izquierda en cualquier parte de la pantalla
- Presionar el icono/título de la aplicación en el action bar.
- Presionar el botón de "Atrás".
El Navigation drawer puede contener títulos. Estos no son interactivos, sólo nos valdrán para organizar los objetivos de navegación en temas.
También podemos añadir a cada objetivo iconos y contadores. Los contadores sirven para informar al usuario cambios en el estado de los datos en la correspondiente vista.
Dentro del Navigation drawer también podemos plegar diferentes elementos que están subordinados a un elemento principal.
Finalmente, unos consejos acerca del estilo. El ancho, naturalmente dependerá del contenido a visualizar, pero como mínimo siempre tendrá 240 dp y un máximo de 320 dp. La altura de cada elemento no deberá superar los 48 dp.
Ejemplo.
Lo primero que haremos será envolver todo el contenido del layout con un DrawerLayout (android.support.v4.widget.DrawerLayout) y añadir un ListView que va a ser el que contenga la lista de navegación.
Hay que tener en cuenta que:
- el principal contenedor de vistas (FrameLayout) debe ser el primer hijo del DrawerLayout.
- Este contenedor debe establecer los parámetros de ancho y alto como todo el contenido del padre pues cuando el navigation drawer esté oculto representará toda la interfaz gráfica.
- La vista del drawer (ListView) debe especificar que usa el atributo "layout_gravity" en horizontal.
El siguiente paso es adjuntar el adaptador a la ListView para inicializar la lista de elemento del navigation drawer.
Vamos a utilizar un ArrayAdapter al que le pasamos un array de Strings que recuperamos de los recursos. Además, necesitamos registrar un callback para poder resonder a la selección de las opciones de navegación.
String[]posicionesDrawer; DrawerLayout dwLayout; ListView lvDrawer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); posicionesDrawer = getResources().getStringArray(R.array.opciones); lvDrawer = (ListView) findViewById(R.id.lvDrawer); dwLayout = (DrawerLayout) findViewById(R.id.dwlayout); ArrayAdapter adaptador = new ArrayAdapter(this, android.R.layout.simple_list_item_1, posicionesDrawer); lvDrawer.setAdapter(adaptador); lvDrawer.setOnItemClickListener(this); }
Cuando recibimos la pulsación de la opción, llamamos al fragmento que queremos cargar.
@Override public void onItemClick(AdapterView padre, View vista, int posicion, long id) { seleccionarPosicion(posicion); } private void seleccionarPosicion(int posicion) { Fragment fragment = new PosicionFragment(); Bundle args = new Bundle(); args.putInt(PosicionFragment.NUMERO_POSICION, posicion); fragment.setArguments(args); android.app.FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.main_frame, fragment) .commit(); lvDrawer.setItemChecked(posicion, true); setTitle(posicionesDrawer[posicion]); dwLayout.closeDrawer(lvDrawer); } @Override public void setTitle(CharSequence titulo) { getActionBar().setTitle(titulo); } public static class PosicionFragment extends Fragment { public static final String NUMERO_POSICION = "numero_posicion"; public PosicionFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragmento, container, false); int i = getArguments().getInt(NUMERO_POSICION); String texto = getResources().getStringArray(R.array.textos_fragmentos)[i]; ((TextView) rootView.findViewById(R.id.tvFragmento)).setText(texto); getActivity().setTitle(texto); return rootView; } }
Reader Comments (3)
Gracias por el tutorial. Algún día tendré que repasar el diseño de la interfaz e intentar adaptarla a la guía que exista en ese momento.
El esfuerzo que ha hecho y está haciendo Google por mejorar la UI es muy importante. Y el tener disponibles indicaciones sobre cómo hacer ciertas acciones y qué patrones usar permite mejorar la usabilidad de las aplicaciones. Sería interesante hacer un repaso a los principales patrones de diseño de Google.
Gracias por el ejemplo, ¿sabéis de algún tutorial para poder incluir los títulos y los counters dentro de la barra lateral? no me termina de quedar claro como hacer eso.
Saludos