Programar en Android sin acabar siendo un mono que teclea (IV): Implementación y diseño del menú lateral

8

En esta nueva entrega de nuestra serie de artículos la cosa se complica un poco. Nos adentraremos en el código, y veréis que, como os dije: no es necesario ser un experto programador en JAVA para crear las Apps, (aunque quizás antes o después conviene adquirir unas nociones básicas). En esta entrega nos centraremos en la creación y configuración del menú lateral, y echaremos a un vistazo a la detección de errores en nuestro código. Éste será el aspecto de nuestra App, al terminar este artículo.

 

6

 

Vamos a comenzar con el menú lateral. Los menús laterales los podemos ver en gran cantidad de Apps, sobre todo desde Ice Cream Sandwhich, que proporcionó un cambio de una estética basada en Dashboard a un nuevo diseño basado en la ActionBar y el menú lateral.

 

2

1

idealista2-framed

 

Lo primero que haremos es crear el archivo XML que tendrá el diseño de nuestro menú lateral, pero antes en , en el archivo styles de la carpeta values copiaremos este código (sin quitar el que actualmente hay, justo antes de </resources>)

 

 <style name="TextoMenu" parent="@android:style/TextAppearance.Medium">
    <item name="android:layout_width">fill_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:textColor">#FFFFFF</item>
    <item name="android:textStyle">bold</item>
    <item name="android:layout_marginLeft">33dp</item>
    
   
</style>

 

El archivo del diseño de nuestro menú lateral lo crearemos en la carpeta layouts. Lo llamaremos menulateral y tendrá el siguiente código XML:

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#2E2E2E" >

    <ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" 
                android:clickable="True"
                android:onClick="Inicio">

                <ImageView
                    android:id="@+id/imageView2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="26dp"
                    android:src="@drawable/inicio" 
                    android:layout_marginTop="5dp"/>

                <TextView style="@style/TextoMenu"
                    android:id="@+id/textView2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="33dp"
                    android:layout_toRightOf="@+id/imageView2"
                    android:text="Inicio"
                  />

            </RelativeLayout>

            <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="1.5dp" 
        android:background="#FFFFFF"
        android:layout_marginTop="10dp">
    </LinearLayout>
    
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" 
                 android:clickable="True"
                android:onClick="Productos">

                <ImageView
                    android:id="@+id/imageView3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentLeft="true"
                    android:layout_alignParentTop="true"
                    android:layout_marginLeft="24dp"
                    android:src="@drawable/productos" />

                <TextView
                    android:id="@+id/textView2"
                    style="@style/TextoMenu"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                  
                    android:layout_toRightOf="@+id/imageView3"
                    android:text="Productos" />

            </RelativeLayout>
            
            <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="1.5dp" 
        android:background="#FFFFFF"
        android:layout_marginTop="10dp">
    </LinearLayout>
              <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                 android:clickable="True"
                android:onClick="Ofertas" >

                <ImageView
                    android:id="@+id/imageView3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentLeft="true"
                    android:layout_alignParentTop="true"
                    android:layout_marginLeft="24dp"
                    android:src="@drawable/ofertas" />

                <TextView
                    android:id="@+id/textView2"
                    style="@style/TextoMenu"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                  
                    android:layout_toRightOf="@+id/imageView3"
                    android:text="Ofertas" />

            </RelativeLayout>
            
              <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="1.5dp" 
        android:background="#FFFFFF"
        android:layout_marginTop="10dp">
    </LinearLayout>
    
                       <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" 
                 android:clickable="True"
                android:onClick="Contacto">

                <ImageView
                    android:id="@+id/imageView3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentLeft="true"
                    android:layout_alignParentTop="true"
                    android:layout_marginLeft="24dp"
                    android:src="@drawable/contacto" />

                <TextView
                    android:id="@+id/textView2"
                    style="@style/TextoMenu"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                  
                    android:layout_toRightOf="@+id/imageView3"
                    android:text="Contacto" />

            </RelativeLayout>
        </LinearLayout>
    </ScrollView>
    
</LinearLayout>

 

Intentaré explicar lo más destacable de este código. No comentaré todos los elementos porque no es mi intención para estos tutoriales. Mi intención es que sepáis modificar estos códigos para adaptarlos a vuestro proyecto. Cada vez que creéis un archivo xml con Eclipse y el SDK de Android tendréis la posibilidad de ir viendo cómo va quedando el diseño e incluso arrastrar y soltar elementos para crear el diseño de una forma visual. Para esto, pincharemos la pestaña Graphical Layout. La pestaña menulateral.xml es la que nos permite modificar el código.

 

3

En la pestaña Graphical Layout miraremos arriba a la derecha , donde pone OutLine, y podremos ver la estructura del nuestro archivo.

 

4

 

 

Los elementos de más a la izquierda contienen a los que están a su derecha. Podemos ver que hay un LinnearLayout que contiene a todos los demás elementos. ¿Qué son los layouts? Los layouts son contenedores de uno o varios elementos que nos permiten un diseño más cómodo de las vistas. El LinnearLayout es el más sencillo de todos. Dentro de un LinnearLayout los elementos siempre se irán colocando automáticamente en una línea horizontal o vertical. Esto dependerá del atributo

 android:orientation="vertical" 

que si nos metemos a la vista de código veremos que está en el primer LinnearLayout.. El siguiente elemento que vemos en nuestro archivo es el ScrollView. El ScrollView lo que permite es, que si no caben todos los elementos en móviles pequeños, puedas desplazarte hacia abajo para ver los demás. El siguiente elemento que vemos es otro Linnear Layout que contiene varios RelativeLayouts y LinnearLayouts, unos debajo de otros (por tener orientación vertical). A partir de aquí, siempre encontramos la misma estructura: Un RelativeLayout con una Imagen y un TextView dentro, y un LinanearLayout debajo.

Los RelativeLayouts permiten asignar posiciones relativas a los elementos. Esto me ha permitido poner la imagen junto al texto con una cierta separación

Los LinnearLayout de debajo simplemente son las barras de separación. Para ello les he dado una altura específica y les he puesto un fondo de color blanco. Esta no es una forma muy correcta de ponerlas, pero quería que me sirviera para poder hablar más de los Layouts.

No voy a explicar el contenido de cada layout. Simplemente decir que cada uno contiene un ImageView que muestra el icono, y un TextView que muestra el texto. Para aprender qué significa cada elemento, y como ubicarlos dentro de los layouts, una de las prácticas que más recomiendo es arrastrar distintos elementos en nuestro editor gráfico y ver cómo cambia el código. Además, poco a poco iré explicando algunos de los más importantes. Para terminar con el diseño del menú lateral me faltaría comentar dos cosas más: las imágenes que he usado y para qué sirve el estilo que he creado anteriormente.

Para las imágenes he vuelto a usar la página Google Assets Studio. He pinchado en Generic Icons, y en la pestaña Cliparts he elegido las imágenes que más se adaptaban. He puesto la configuración de la imagen y he descomprimido cada archivo que se descargaba, en la carpeta del proyecto.

0

 

Los nombres que he puesto respectivamente para las imagenes (muy importante que sean estos, de lo contrario el código no encontrará la imagen) son respectivamente: inicio, productos, oferta, contacto. Tras haber subido todas pulsaremos con el botón derecho en el proyecto y pincharemos en Refresh.

Con respecto al diseño, si nos volvemos a ir al código del archivo menulateral podemos ver como dentro de todos los TextView se puede ver este elemento: @style/TextoMenu El estilo que anteriormente habíamos creado, nos ha permitido no tener que repetir las mismas configuraciones en todos los TextView. Dentro del estilo hemos definido el color, tamaño, estilo… de todos los textos a los que se lo asignáramos.

Procedemos ahora a implementar el menú lateral a nuestra App. Para ello, nuevamente volveremos a necesitar una nueva librería, que descargaremos de aquí. Descomprimiremos la librería en nuestra carpeta de proyectos. Después en eclipse nos iremos a File>Import>Existing Android Project into WorkSpace, y nos iremos a la carpeta que acabamos de descomprimir, donde nos aparecerá la librería. Clickaremos en él, y luego en Finish. De la misma forma que hicimos con ActionBarSherlock la añadimos a nuestro proyecto. (Puede que os de algún problema, luego os diré cómo podéis ver la causa del problema para qué os pueda dar una solución)

Ahora iremos a la carpeta src>com.example.mitiendaandroid y abrimos el archivo MainActivity.java. Modificaremos el código, para que quede así:
 

package com.example.mitiendaandroid;

import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;




public class MainActivity extends SherlockActivity {

	SlidingMenu menu;
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		
		Display display = getWindowManager().getDefaultDisplay();
		@SuppressWarnings("deprecation")
		int width = display.getWidth();
		
		
	    menu = new SlidingMenu(this);
	    menu.setMode(SlidingMenu.LEFT);
	    menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
	   
	    menu.setShadowWidth(20);
	    menu.setBehindOffset(30);
	    menu.setFadeDegree(0.25f);
	    menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
	    menu.setBehindWidth(width-60);
	    menu.setMenu(R.layout.menulateral);
	    menu.showMenu(true);
  
	}

	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getSupportMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return true;
    }
	
	@Override
	public void onBackPressed() {
		if(menu.isMenuShowing()){menu.toggle();}
		else {finish();}
		
	}

}

 

Lo que hemos hecho es detectar el tamaño de la pantalla, y luego añadir el menú lateral, asignándole la vista que le hemos creado y 60 píxeles menos que el ancho total de nuestra pantalla.

Esta parte es muy importante también

 

	@Override
	public void onBackPressed() {
		if(menu.isMenuShowing()){menu.toggle();}
		else {finish();}
		
	}

 
Lo que hace es detectar cuando pulsamos el botón atrás, y comprobar si el menú esta abierto. Si es así, cerramos el menú. Si el menú ya está cerrado, cierra la aplicación.

 

Para terminar el artículo, os explicaré cómo podéis comprobar a qué se deben los fallos en vuestra aplicación.

Como he dicho antes,  el hecho de que haya dos librerías en nuestra App, puede dar lugar a algún error. Para ver información sobre los errores, en  Eclipse contamos con las pestañas Console,  LogCat, y Problems. Dentro de éstas se ofrecerá información sobre qué está haciendo nuestra aplicación en cada momento y algunos problemas que hay con nuestros proyectos. Cualquier error que tengáis, no dudéis en pasarme el código que os aparece en el LogCat (los errores salen en rojo) y será mucho más fácil solucionarlo. Y como siempre, agradezco vuestros comentarios sean positivos o negativos, atenderé a todos.

Share.

About Author

Mi nombre es Pablo González Carrizo, aunque mi seudónimo en este mundo sea Un mono que teclea. Mis estudios de Imagen y Sonido en Telecomunicaciones me permiten estar informado de todas las novedades en tecnología, que intento siempre compartir.

8 comentarios

  1. Jesus Miranda on

    Hola, podrías ayudarme con el código fuente del ejercicio, ya que no encuentro el link para descargarlo…
    Te lo agradecería muchísimo
    Saludos

    • Pablo González Carrizo on

      Perdón por la tardanza. En la siguiente entrada tienes el código fuente.
      Un saludo

  2. pacopunta on

    Me sale este error y la aplicacion se cierra:

    Cómo solucionarlo, ya he ido a path y marcado las librerias….limpiado el proyecto y construido nuevamente, pero el error sigue.

    gracias

    
    08-11 11:06:59.630: E/AndroidRuntime(2829): FATAL EXCEPTION: main
    08-11 11:06:59.630: E/AndroidRuntime(2829): java.lang.NoClassDefFoundError: com.actionbarsherlock.R$styleable
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at com.actionbarsherlock.internal.ActionBarSherlockCompat.generateLayout(ActionBarSherlockCompat.java:973)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at com.actionbarsherlock.internal.ActionBarSherlockCompat.installDecor(ActionBarSherlockCompat.java:902)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at com.actionbarsherlock.internal.ActionBarSherlockCompat.setContentView(ActionBarSherlockCompat.java:836)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at com.actionbarsherlock.app.SherlockActivity.setContentView(SherlockActivity.java:229)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at es.pacopunta.mitiendaandroid.MainActivity.onCreate(MainActivity.java:24)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at android.os.Handler.dispatchMessage(Handler.java:99)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at android.os.Looper.loop(Looper.java:130)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at android.app.ActivityThread.main(ActivityThread.java:3687)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at java.lang.reflect.Method.invokeNative(Native Method)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at java.lang.reflect.Method.invoke(Method.java:507)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
    08-11 11:06:59.630: E/AndroidRuntime(2829): 	at dalvik.system.NativeStart.main(Native Method)
    
    
    
    • Pablo González Carrizo on

      El problema tiene que ser del Path. Pruba con el código fuente que he subido en el siguiente artículo. Y si te vuelve a dar problema con las librerías, puedes contactar conmigo en unmonoqueteclea.es para no saturar demasiado los comentarios. Y así podemos ver detenidamente cual es el problema

      Un saludo, espero que te esté siendo útil.

      • pacopunta on

        No encuentro la seccion en la web

        aún así he probado con tu código y me sale el mismo error, he instalado el soporte en el path y sigue error

        08-12 14:38:06.842: E/AndroidRuntime(4683): at com.jeremyfeinstein.slidingmenu.lib.CustomViewAbove.(CustomViewAbove.java:157)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at com.jeremyfeinstein.slidingmenu.lib.CustomViewAbove.(CustomViewAbove.java:152)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.(SlidingMenu.java:209)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.(SlidingMenu.java:192)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.(SlidingMenu.java:171)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at es.pacopunta.mitiendaandroid.ActividadBase.onCreate(ActividadBase.java:35)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at es.pacopunta.mitiendaandroid.MainActivity.onCreate(MainActivity.java:26)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at android.os.Handler.dispatchMessage(Handler.java:99)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at android.os.Looper.loop(Looper.java:130)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at android.app.ActivityThread.main(ActivityThread.java:3687)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at java.lang.reflect.Method.invokeNative(Native Method)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at java.lang.reflect.Method.invoke(Method.java:507)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
        08-12 14:38:06.842: E/AndroidRuntime(4683): at dalvik.system.NativeStart.main(Native Method)

  3. pacopunta on

    este es otro error

    
    08-22 08:30:31.015: E/AndroidRuntime(14991): FATAL EXCEPTION: main
    08-22 08:30:31.015: E/AndroidRuntime(14991): java.lang.NoClassDefFoundError: android.support.v4.view.ViewConfigurationCompat
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at com.jeremyfeinstein.slidingmenu.lib.CustomViewAbove.initCustomViewAbove(CustomViewAbove.java:167)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at com.jeremyfeinstein.slidingmenu.lib.CustomViewAbove.(CustomViewAbove.java:157)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at com.jeremyfeinstein.slidingmenu.lib.CustomViewAbove.(CustomViewAbove.java:152)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.(SlidingMenu.java:209)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.(SlidingMenu.java:192)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.(SlidingMenu.java:171)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at es.pacopunta.mitiendaandroid.MainActivity.onCreate(MainActivity.java:36)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at android.app.Activity.performCreate(Activity.java:5206)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at android.app.ActivityThread.access$600(ActivityThread.java:140)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at android.os.Handler.dispatchMessage(Handler.java:99)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at android.os.Looper.loop(Looper.java:137)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at android.app.ActivityThread.main(ActivityThread.java:4898)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at java.lang.reflect.Method.invokeNative(Native Method)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at java.lang.reflect.Method.invoke(Method.java:511)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1008)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:775)
    08-22 08:30:31.015: E/AndroidRuntime(14991): 	at dalvik.system.NativeStart.main(Native Method)
    
  4. Muchas gracias por el tutorial, funciona perfectamente bien, excelente aporte

    Saludos

  5. Hola, estoy empezando a seguir tus tutoriales y son lo mejor que hay , MUCHISIMAS GRACIAS !!!!
    Me gustaría saber como deberia implementar la barra lateral para que no se me abra al arrancar la aplicación.
    Un saludo y muchas gracias.

Leave A Reply

Uso de cookies

Este sitio web utiliza cookies para una mejor experiencia de usuario. Si continúas navegando estás dando tu consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies