NavigationView - Como implementar un menú desplegable en Android

Buen día, el día de hoy les comparto este breve tutorial de como implementar el control NavigationView en Android, debido a la nueva guía de diseño Material Design este control viene a reemplazar al control NavigationDrawer para incorporar un menú desplegable de opciones en nuestra app.

Este control permite tener incorporado varios elementos dentro de él. La principal característica es que nos permite tener una cabecera que permite mostrar al usuario información o algún otro elemento, además, de agrupar las opciones para diferenciarlas entre ellas; como en la siguiente imagen:



Lo primero que haremos es crear un nuevo proyecto desde Android Studio, en mi caso lo nombre como NavigationDrawerApp, recuerden que debemos seleccionar una plantilla vacía (Empty Activity).

Se debe configurar previamente nuestra aplicación para utilizar Toolbar, mediante la modificación del archivo styles.xml de nuestra app, en el cual agregaremos el siguiente código:

<resources>

  <!-- Base application theme. -->
  <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
  </style>
  <style name="AppTheme.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
  </style>
  <style name="AppTheme.AppBarOverlay"
         parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
  <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>

</resources>

Además, debemos crear una carpeta de recursos que debemos nombrar values-v21 dentro de la carpeta res de nuestro proyecto, así como una vez creado el directorio, debemos generar un archivo xml nombrado como styles.xml dentro de ella, y debemos agregar el siguiente código:

<resources>
  <style name="AppTheme.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
  </style>
</resources>

Una vez que se tengan los archivos de estilos en nuestra aplicación, el siguiente paso es asignarle a ella, el tema que corresponde para que no muestre el actionbar, y en vez de ello muestre nuestro Toolbar,  como en el siguiente código en el archivo AndroidManifest.xml de nuestra app, y debemos modificar la etiqueta application como se muestra en el siguiente código:

<application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:theme="@style/AppTheme.NoActionBar">

Una vez que tengamos construido la estructura del proyecto, debemos de generar un archivo layout en la carpeta correspondiente:



Una vez que se tenga el archivo xml, debemos de agregar los elementos para generar la vista de nuestra cabecera para nuestro menú, el siguiente código muestra la distribución de los elementos que deseo contener en ella:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="250dp"
              android:background="@color/colorPrimary"
              android:gravity="bottom"
              android:orientation="vertical"
              android:paddingBottom="@dimen/activity_vertical_margin"
              android:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin"
              android:theme="@style/ThemeOverlay.AppCompat.Dark">

  <ImageView
      android:id="@+id/imageView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:paddingTop="10dp"
      android:src="@android:drawable/sym_def_app_icon"/>

  <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:paddingTop="10dp"
      android:text="NavigationView Example"
      android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

  <TextView
      android:id="@+id/textView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="NavigationViewExample@example.com"/>

</LinearLayout>

ahora lo que debemos de realizar es estructurar nuestra vista de la actividad principal para incorporar el menú desplegable, es necesario seguir utilizando el elemento DrawerLayout como controlador de nuestro menú, lo primero es que agregaremos otro layout en el cual configuraremos nuestra barra de aplicaciones (AppBar), lo nombraremos "app_bar_main",  el código es el siguiente

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.cybertech.navigationviewapp.MainActivity">

  <android.support.design.widget.AppBarLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"/>

  </android.support.design.widget.AppBarLayout>

  <include layout="@layout/content_main"/>

  <android.support.design.widget.FloatingActionButton
      android:id="@+id/fab"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="bottom|end"
      android:layout_margin="48dp"
      android:src="@android:drawable/ic_dialog_email"/>

</android.support.design.widget.CoordinatorLayout>

ahora lo siguiente es agregar otro layout a nuestro proyecto, este se nombrara como"content_main" y este es su código:


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="+@id/cointaner_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.cybertech.navigationviewapp.MainActivity"
    tools:showIn="@layout/app_bar_main">

  
</FrameLayout>

En nuestro layout "activity_main" reemplazamos el código que se tiene, por el que está a continuación:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

  <include
      layout="@layout/app_bar_main"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>

  <android.support.design.widget.NavigationView
      android:id="@+id/nav_view"
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:layout_gravity="start"
      android:fitsSystemWindows="true"
      app:headerLayout="@layout/menu_header"
      app:menu="@menu/activity_main_drawer"/>

</android.support.v4.widget.DrawerLayout>

En este archivo, es donde se agrega el elemento NavigationView en nuestra aplicación, es a través de la etiqueta "headerLayout" donde se indica el layout de cabecera que se definió anteriormente y en la etiqueta "menu" es donde se establece las opciones que va a contener. Hasta aquí, hemos configurado nuestras vistas que utilizaremos en nuestra actividad, incorporando los elementos necesarios para contener un menu desplegable, para el correcto funcionamiento se requiere generar las opciones del menú desplegable, esto se logra a través de generar un archivo de menú en nuestro proyecto, para ello debemos crear la carpeta "menu" en nuestra carpeta de recursos de nuestra aplicación:


<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

  <group android:checkableBehavior="single">
    <item
        android:id="@+id/nav_camera"
        android:icon="@drawable/ic_menu_camera"
        android:title="Import"/>
    <item
        android:id="@+id/nav_gallery"
        android:icon="@drawable/ic_menu_gallery"
        android:title="Gallery"/>
    <item
        android:id="@+id/nav_slideshow"
        android:icon="@drawable/ic_menu_slideshow"
        android:title="Slideshow"/>
    <item
        android:id="@+id/nav_manage"
        android:icon="@drawable/ic_menu_manage"
        android:title="Tools"/>
  </group>

  <item android:title="Communicate">
    <menu>
      <item
          android:id="@+id/nav_share"
          android:icon="@drawable/ic_menu_share"
          android:title="Share"/>
      <item
          android:id="@+id/nav_send"
          android:icon="@drawable/ic_menu_send"
          android:title="Send"/>
    </menu>
  </item>

</menu>

En estas opciones es muy similar a establecer un menú en Android, en esté se agrupan ciertas opciones para mostrarlas separadas de otras, en cada una de las opciones además de indicar un identificador y un titulo para la opción, se indica un icono en cada uno de ellos, en este ejemplo no utilizaremos imágenes jpg o png, sino imágenes creadas a partir de vectores que se definen en un archivo xml que a continuación dejo su código de cada una

ic_menu_camera

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
  <path
      android:fillColor="#FF000000"
      android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
  <path
      android:fillColor="#FF000000"
      android:pathData="M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>


ic_menu_gallery

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
  <path
      android:fillColor="#FF000000"
      android:pathData="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z"/>
</vector>

ic_menu_manage

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
  <path
      android:fillColor="#FF000000"
      android:pathData="M22.7,19l-9.1,-9.1c0.9,-2.3 0.4,-5 -1.5,-6.9 -2,-2 -5,-2.4 -7.4,-1.3L9,6 6,9 1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1,0.4 1.4,0l2.3,-2.3c0.5,-0.4 0.5,-1.1 0.1,-1.4z"/>
</vector>

ic_menu_send

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
  <path
      android:fillColor="#FF000000"
      android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>

ic_menu_share

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
  <path
      android:fillColor="#FF000000"
      android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>

ic_menu_slideshow

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
  <path
      android:fillColor="#FF000000"
      android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z"/>
</vector>

slide_nav_bar

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
  <gradient
      android:angle="135"
      android:centerColor="#4CAF50"
      android:endColor="#2E7D32"
      android:startColor="#81C784"
      android:type="linear"/>
</shape>

Ahora debemos implementar en nuestra clase el control de nuestro menú desplegable para que funcione en nuestra actividad, debemos implementar el código en el metodo onCreate de nuestra clase, lo primero que debemos realizar es obtener el Toolbar definido en nuestra vista xml e implementarlo:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
  }

Una vez definido ahora debemos obtener el control de nuestro DrawerLayout e implementar la interface que controle los estados de nuestro menú desplegable y asignarlo a nuestro drawer para que esté pueda reaccionar a los eventos del usuario:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(this,
        drawerLayout,toolbar,R.string.drawer_open,R.string.drawer_closed);
    drawerLayout.addDrawerListener(drawerToggle);
    drawerToggle.syncState();

  }

A continuación debemos agregar el control de nuestro menú en el momento que el usuario seleccione una opción de esté:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(this,
        drawerLayout,toolbar,R.string.drawer_open,R.string.drawer_closed);
    drawerLayout.addDrawerListener(drawerToggle);
    drawerToggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
      @Override
      public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
          case R.id.nav_camera:
            Toast.makeText(getBaseContext(),"Camara seleccionada",Toast.LENGTH_SHORT).show();
            return true;
          case R.id.nav_gallery:
            Toast.makeText(getBaseContext(),"Galeria seleccionada",Toast.LENGTH_SHORT).show();
            return true;
          case R.id.nav_slideshow:
            Toast.makeText(getBaseContext(),"Presentación seleccionada",Toast.LENGTH_SHORT).show();
            return true;
          case R.id.nav_manage:
            Toast.makeText(getBaseContext(),"Herramientas seleccionada",Toast.LENGTH_SHORT).show();
            return true;
          case R.id.nav_share:
            Toast.makeText(getBaseContext(),"Compartir seleccionada",Toast.LENGTH_SHORT).show();
            return true;
          case R.id.nav_send:
            Toast.makeText(getBaseContext(),"Enviar seleccionada",Toast.LENGTH_SHORT).show();
            return true;
          default:
            return false;
        }
      }
    });
  }

Así es como finalizamos esta práctica, y una vez terminado podrán ejecutarlo, así como tener su propio menú desplegable utilizando Material Design.

Aqui les dejo el video del ejemplo:



Comentarios

Entradas populares