OO en Android, cómo poner el menú de navegación principal en una sola clase

¿Programas apps Android? Pues seguro que alguna vez has necesitado que dos o más ActionBarActivity compartan exactamente el mismo menú principal de navegación.

Como ya sabéis amig@s seguidores, estos días vengo aprendiendo y mejorando mis habilidades Android. Como estoy bastante entusiasmado con ello, hoy vengo con un truco Orientado a Objetos.

Herencia OO para la navegación principal

En un caso como el anterior no tiene sentido que te pongas a repetir el mismo código en todas tus actividades; eso dificultará el mantenimiento. Muy al contrario, te interesa utilizar la herencia OO para encapsular la navegación en un único punto de tu app y poder reutilizar fácilmente ese código.

Figura 1. Poniendo la navegación principal de la app en una sola clase

Figura 1. Poniendo la navegación principal de la app en una sola clase

Código Java de las actividades

Entonces te cuento que yo he puesto la navegación principal en esta superclase llamada MyAppActionBarActivity que hereda de ActionBarActivity:

MyAppActionBarActivity.java

package com.programarivm.myapp;

import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MyAppActionBarActivity extends ActionBarActivity {

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id == R.id.action_myapp) {
            finish();
            startActivity(getIntent());
            return true;
        }

        if (id == R.id.action_about) {
            setContentView(R.layout.activity_about);
            return true;
        }

        if (id == R.id.action_contact) {
            setContentView(R.layout.activity_contact);
            return true;
        }

        if (id == R.id.action_visit_our_website) {
            setContentView(R.layout.activity_webview);
            final ProgressDialog dialogVisitWeb = new ProgressDialog(MyAppActionBarActivity.this);
            WebView visitweb = (WebView) findViewById(R.id.webview);
            visitweb.getSettings().setJavaScriptEnabled(true);
            visitweb.setWebViewClient(new WebViewClient(){
                @Override
                public void onPageFinished(WebView view, final String url) {
                    dialogVisitWeb.cancel();
                }
                @Override
                public void onPageStarted(WebView view, String url, Bitmap favicon) {
                    dialogVisitWeb.setMessage("Please wait...");
                    dialogVisitWeb.show();
                }
            });
            visitweb.loadUrl("https://example.com");
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

}

De modo que todas las actividades de mi app pueden compartir la misma navegación. Por cierto, fíjate que el menú de navegación contiene una WebView para poder mostrar una página web.

MainActivity.java

package com.programarivm.myapp;

import android.os.Bundle;

public class MainActivity extends MyAppActionBarActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    
}

Código XML del menú principal

El código xml del menú de navegación está en res\menu\menu_main.xml:

<menu 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" tools:context=".MainActivity">

    <item android:id="@+id/action_myapp" android:title="MyApp"
        android:orderInCategory="100" app:showAsAction="never" />

    <item android:id="@+id/action_about" android:title="Sobre nosotros"
        android:orderInCategory="100" app:showAsAction="never" />

    <item android:id="@+id/action_contact" android:title="Contacto"
        android:orderInCategory="100" app:showAsAction="never" />

    <item android:id="@+id/action_visit_our_website" android:title="Visita nuestra web"
        android:orderInCategory="100" app:showAsAction="never" />
</menu>

Código XML de los layouts

Ya falta poco. Ahora, en res\layout tenemos que ir poniendo los xml de las opciones del menú de navegación principal (Sobre nosotros y Contacto).

Ya casi lo tenemos

res\layout\activity_about.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillViewport="true"
    android:background="#FFFFFF"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:paddingTop="5dp"
        android:paddingRight="35dp"
        android:paddingBottom="35dp"
        android:paddingLeft="35dp" >

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:gravity="left|top"
            android:text="Hola, ¡esta es la página Sobre nosotros!"
            android:textColor="#000000"
            android:layout_alignParentTop="true"
            android:layout_alignParentStart="true" />

    </LinearLayout>

</ScrollView>

res\layout\activity_contact.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillViewport="true"
    android:background="#FFFFFF"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:paddingTop="5dp"
        android:paddingRight="35dp"
        android:paddingBottom="35dp"
        android:paddingLeft="35dp" >

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:gravity="left|top"
            android:text="Hola, ¡esta es la página de contacto!"
            android:textColor="#000000"
            android:layout_alignParentTop="true"
            android:layout_alignParentStart="true" />

    </LinearLayout>

</ScrollView>

Y también tenemos que poner el código de res\layout\activity_main.xml y res\layout\activity_webview.xml.

res\layout\activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillViewport="true"
    android:background="#FFFFFF"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical"
            android:paddingTop="5dp"
            android:paddingRight="35dp"
            android:paddingBottom="35dp"
            android:paddingLeft="35dp" >

            <TextView android:text="@string/hello_world" android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

        </LinearLayout>

</ScrollView>

res\layout\activity_webview.xml

<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" android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    android:paddingBottom="0dp" tools:context=".MainActivity">

    <WebView  xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentTop="true" />

</RelativeLayout>

Código XML del Android Manifest

Como MyApp necesita acceder a Internet para poder mostrar la página web, necesita los correspondientes permisos de acceso en el AndroidManifest.

manifests\AndroidManifest.xml

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <uses-permission android:name="android.permission.INTERNET" />

</manifest>

¡Hasta pronto amig@s!

Como os digo, ando mejorando mis habilidades Android, así que es posible que haya alguna cosita que se pueda mejorar, ¡pero el código funciona bien! Te invito a comentarlo en las redes sociales: en Twitter y en Google+.

Muchas gracias y saludos. Que tengas una buena semana.