sábado, 4 de octubre de 2014

NavigationDrawer

Se trata de un panel que aparece desde la parte izquierda de la pantalla, ya sea al pulsar en la barra de navegación, como al realizar gesto de desplazamiento a la derecha.
Es una práctica muy habitual en la actualidad el uso de este tipo de menú de opciones.

Compatibilidad

v14 – interacción con ActionBar y HomeButton
Inferiores con support.v7 o ActionBarSherlock

Lo mínimo necesario

Layout para la Activity:
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- Vista principal -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!-- Navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@color/drawer_divider"
        android:dividerHeight="0dp"
        android:background="@color/drawer_background"/>
</android.support.v4.widget.DrawerLayout>

Activity principal:
  • Inicializar el drawer
public class MainActivity extends Activity implements OnItemClickListener{
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        final CharSequence mTitle = getTitle();

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        //Sombra para cuando se abre el drawer
        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
   GravityCompat.START);
        //Establecer las opciones del drawer
        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.item_drawer_list,
                getResources().getStringArray(R.array.opciones)));
        mDrawerList.setOnItemClickListener(this);

        //Necesario para que el botón home abra y cierre el drawer
        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        //Controla las interacciones entre el drawer y el actionbar
        mDrawerToggle = new ActionBarDrawerToggle(
                this,                  /* Activity */
                mDrawerLayout,         /* DrawerLayout */
                R.drawable.ic_drawer/* icono que reemplaza al 'Up' */
                R.string.drawer_open/* cadena para accesibilidad */
                R.string.drawer_close  /* cadena para accesibilidad */
                ) {
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu(); // Fuerza la carga del menú             
      }

            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu(); // Fuerza la carga del menú             
      }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        //Opción por defecto
        if (savedInstanceState == null) {
            selectItem(0);
        }
    }

  • Evento al seleccionar opción
@Override
       public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
             selectItem(position);
       }
      
       /**
        * Acción a ejecutar tras seleccionar una opción
        * @param position índice de la opción seleccionada
        */
       private void selectItem(int position) {
       
    }

  • Abrir drawer al seleccionar HomeButton
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        //Sincronizar el estado del toggle
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        //Pasar la actualización de estado al toggle
        mDrawerToggle.onConfigurationChanged(newConfig);
    }
   
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //Abrir o cerrar el drawer
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }

        return super.onOptionsItemSelected(item);

    }


Personalización

Adapter personalizado para la construcción del drawer:
//Cargar los datos de los elementos
TypedArray titulos = getResources().obtainTypedArray(R.array.drawer_list);
TypedArray iconos = getResources().obtainTypedArray(R.array.drawer_icon);
                          
ArrayList<DrawerItem> items = new ArrayList<DrawerItem>();
for (int i=0; i<titulos.length(); i++){
       items.add(new DrawerItem(titulos.getString(i),
                                               iconos.getResourceId(i, -1));
}
                          
titulos.recycle();
iconos.recycle();

//Establecer adaptador
NavDrawerAdapter adapter = new NavDrawerAdapter(this,
R.layout.item_drawer_list, items);
mDrawerList.setAdapter(adapter)

Navegación

La navegación desde las opciones del drawer debe ser lateral. La navegación lateral se determina a través de fragments.
La navegación Up se proporciona al entrar en el detalle de alguno de los fragments principales, lanzando un nuevo Activity. En el Manifest se declara para esta Activity cuál es la Activity padre:
<activity
android:name="es.hubiqus.drawer.NoticiasActivity"
android:label="@string/app_name"
android:configChanges = "orientation|screenSize"
android:parentActivityName="es.hubiqus.drawer.MainActivity" >
        <!-- The meta-data element is needed for versions lower than 4.1 -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="es.hubiqus.drawer.MainActivity" />
</activity>

En la Activity:
  • Habilitar el HomeButton como atrás
protected void onCreate(Bundle savedInstanceState) {
...
       
getActionBar().setDisplayHomeAsUpEnabled(true);

  • Volver al parent al pulsarlo
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
        case android.R.id.home:
             //Volver al parent
             NavUtils.navigateUpFromSameTask(this);
             return true;
        default:
            return super.onOptionsItemSelected(item);
        }
       }

Cabe destacar del código anterior que es necesario que el Activity parent mantenga el estado tras el lanzamiento, ya que el navigate Up provoca una recarga de dicho Activity.
En caso de un ciclo de vida simple de la app se puede sustituir por un simple finish().

Referencias


No hay comentarios:

Publicar un comentario