Drawer menu con Action Bar y Tabs

Blog >Lista Soluciones > -Drawer Menu + Action Bar + Tabs




Drawer menu manejando ActionBar con Tabs

En el post iremos viendo en Android Studio un menú de navegación vistoso paso a paso, en primer lugar crearemos el menú drawer.

Si quereis ver qué es un menú drawer podeis verlo desde aquí. En este caso cambiaremos los parámetros para que modificar la interfaz visual desde el drawer menu al ActionBar, y en esta ocasión también trataremos el ActionBar con pestañas.

Vamos allá con el código :

 1 Creacción del Drawer Menu

CLASE itemsMenuDrawer

/**
 * Created by makone
 * Description : Encapsula objetos para el menú del Dawer
 */
public class itemsMenuDrawer {
  private int id;
  private String name;
  private String subName;
  private Drawable icon;

  public itemsMenuDrawer(int id, String name, String subName, Drawable icon) {
    this.id = id;
    this.name = name;
    this.subName = subName;
    this.icon = icon;
  }

  public int getId() { return id; }
  public void setId(int id) { this.id = id; }

  public String getName() { return name; }
  public void setName(String name) { this.name = name; }

  public String getSubName() { return subName; }
  public void setSubName(String subName) { this.subName = subName; }

  public Drawable getIcon() { return icon; }
  public void setIcon(Drawable icon) { this.icon = icon; }
}



CLASE menuAdapter
/**
 * Created by makone.
 * Description : Adapter para los objetos del Drawer
 */
public class menuAdapter extends BaseAdapter {

  protected Activity activity;
  //ARRAYLIST CON TODOS LOS ITEMS
  protected ArrayList items;
    
  //CONSTRUCTOR
  public menuAdapter(Activity activity, ArrayList items) {
    this.activity = activity;
    this.items = items;
  }

  //CUENTA LOS ELEMENTOS
  @Override
  public int getCount() {
        return items.size();
    }
  //DEVUELVE UN OBJETO DE UNA DETERMINADA POSICION
  @Override
    public Object getItem(int arg0) {
        return items.get(arg0);
    }

    //DEVUELVE EL ID DE UN ELEMENTO
    @Override
      public long getItemId(int position) {
        return items.get(position).getId();
    }

      //METODO PRINCIPAL, AQUI SE LLENAN LOS DATOS
      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        //ASOCIAMOS LA VISTA AL LAYOUT DEL RECURSO XML DONDE ESTA LA BASE DE
        if (convertView == null) {
          LayoutInflater inf = (LayoutInflater) activity.
                    getSystemService(activity.getApplicationContext().LAYOUT_INFLATER_SERVICE);
          v = inf.inflate(R.layout.itemdrawer, null);
        }

        itemsMenuDrawer dir = items.get(position);
        //RELLENAMOS LA IMAGEN Y EL TEXTO
        ImageView foto = (ImageView) v.findViewById(R.id.img_menu);
        foto.setImageDrawable(dir.getIcon());
        TextView txtPrinc = (TextView) v.findViewById(R.id.txt_princip);
        txtPrinc.setText(dir.getName());
        TextView txtSecund = (TextView) v.findViewById(R.id.txt_secund);
        txtSecund.setText(dir.getSubName());

        // DEVOLVEMOS VISTA
        return v;
    }
}


CLASE MainActivity

public class MainActivity extends ActionBarActivity {
  DrawerLayout drawerLayout;
  FrameLayout contenedorPrincipal;
  ListView listaMenu;
  private ArrayList array;

  Activity activity;
  Context context;

  @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      this.activity = MainActivity.this;
      this.context = activity.getApplicationContext();
      gestionDatos();

    }
  
  public void gestionDatos(){
    instanciarObjetos ();
    configurarMenuDrawer();
  }

  public void configurarMenuDrawer(){

  }

  public void instanciarObjetos (){
    contenedorPrincipal=(FrameLayout) findViewById(R.id.contenedor_principal);
    drawerLayout = (DrawerLayout) findViewById(R.id.menu_drawer);

    listaMenu = (ListView) findViewById(R.id.lista_menu);
    listaMenu.setOnItemClickListener(new AdapterView.OnItemClickListener(){
      @Override
        public void onItemClick(AdapterView parent, View view,int position, long id) {
          seleccionarFragment(position);
        }

    });
      
    View header=getLayoutInflater().inflate(R.layout.header_menu, null); //HEADER
    listaMenu.addHeaderView(header,null,false);

    array = new ArrayList();
    llenarListaMenu(array);

    menuAdapter adaptador = new menuAdapter(this, array);             //ADAPTER
    listaMenu.setAdapter(adaptador);
  }
    
  public void seleccionarFragment(int posicion){
    switch (posicion) {
      // BOTON PLAY, PRIMERA POSICION = 0
      case 1:
        //fragment1
        break;
      case 2:
        //fragment2
        break;
      case 3:
        //fragment3
        break;
      case 4:
        //fragment4
        break;
      case 5:
        finish();
      }
  }
  //LLENAR LISTA DE OBJETOS DEL MENU
  public void llenarListaMenu(ArrayList  arraydir){
    itemsMenuDrawer item;
    // Introduzco los elementos
    item = new itemsMenuDrawer(1, "Nirvana", "Heart, sharped box",
                          context.getResources().getDrawable(R.drawable.ico1));
    arraydir.add(item);
    item = new itemsMenuDrawer(2, "The pixies", "Where is my mind",
                          context.getResources().getDrawable(R.drawable.ico2));
    arraydir.add(item);
    item = new itemsMenuDrawer(3,"Bob Dylan","Hurrican Carter",
                          context.getResources().getDrawable(R.drawable.ico3));
    arraydir.add(item);
    item = new itemsMenuDrawer(4, "Toxicity","System of a down",
                          context.getResources().getDrawable(R.drawable.ico4));
    arraydir.add(item);
    item = new itemsMenuDrawer(5, "Maneras de vivir", "Rosendo",
                          context.getResources().getDrawable(R.drawable.ico5));
    arraydir.add(item);
  }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the actionBar if it is present.
      getMenuInflater().inflate(R.menu.menu_main, menu);
      return true;
    }

  @Override
    public boolean onOptionsItemSelected(MenuItem item) {
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      switch (item.getItemId()) {
              return super.onOptionsItemSelected(item);
      }
  }
}//END CLASS

Este es el resultado :




Si quereis ver cómo se hacen los diseños de R.layout.itemdrawer o el propio activity_main podeis verlo en el post anteriormente mencionado aquí.


2 Implementamos una Action Bar

Antes vamos a insertar la librería de compatibilidad con versiones anteriores, así que le damos click derecho al proyecto y en open module settings (penúltima por abajo), vamos a dependencies y en el + Library Dependency buscamos com.android.support:appcompat-v7.




Podemos usarla para toda la aplicación o para alguna actividad que nos interese.


Ahora vamos a darle un menú a la Action Bar independiente del Drawer, esto a la hora de desarrollar la aplicación es muy importante estudiar este combo, ya que debemos eliminar la redundancia de información.


En este caso en particular, vamos a cambiar los parámetros para que cambie la interfaz visual desde el drawer menu al Action Bar.

Para manejar los iconos que deben ir en la Action Bar creamos una clase en el que le pasamos la opción y genera una Action Bar diferente dependiendo de donde se llame : 


CLASE configActionBAR

import texto.cifrador.makone.cifradortexto.R;

/**
 * Created by makone.
 * Description : Gestiona los menús que deben salir en cada actividad
 */
public class configActionBAR {

  ActionBar actionBar = null;
  int opcion;

  public configActionBAR(ActionBar menu, int opcion) {
    this.actionBar = menu;
    this.opcion = opcion;
    ClasificarMenu(opcion);
  }

  public void ClasificarMenu(int opcion) {
    switch (opcion) {
      case 1:cifrador();

      case 2:

      case 3:
   
      default:
        Log.e("BotoonesMenu", "Opcion incorrecta");
    }
  }

  public void cifrador (){
    //actionBar.hide();                        //Ocultar ActionBar
    actionBar.setIcon(R.drawable.ic_launcher); //Establecer icono
    actionBar.setTitle("Cifrador");            //Establecer titulo
    actionBar.setSubtitle("Menu principal");   //Establecer Subtitulo

    // actionBar.setDisplayHomeAsUpEnabled(true); //Boton atras
    }
}


Y para darle la funcionalidad al botón de atrás de la Action Bar, vamos al método onOptionsItemSelected de MainActivity, donde android.R.id.home es la instancia del botón atrás del ActionBar. 


CLASE MainActivity
 @Override
    public boolean onOptionsItemSelected(MenuItem item) {
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      switch (item.getItemId()) {
          case android.R.id.home :
              drawerLayout.openDrawer(Gravity.LEFT);
              return true;

Usamos la nueva clase para poner los items en lista desplegable o en el título que nos parezca 
 
CLASE MainActivity
 
  public void configurarMenuDrawer(){
    actionBar = getSupportActionBar();
  }
  //EN EL ONCLICK DE listaMenu PARA PODER DARLE OTRA APARIENCIA DEPENDIENDO DEL FRAGMENT
  ACM = new configActionBAR(actionBar,position);
  


Ahora vamos a modificar el menú principal activity_main.xml, pero antes veamos estos atributos :
 
  • ifRoom :    Muestra el icono si lo tiene y tiene espacio. 
  • withText : Icono + título si tiene espacio.
  • always :     Siempre muestra el icono. 
  • never :       Unicamente estará en el desplegable. 
Con always hay que tener cuidado, ya que en pasadas versiones los tamaños eran más pequeños y puede dar problemas, con ifRoom está solucionado, ahora sólo nos hace falta jugar un poco con las propiedades : 

<menu xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  xmlns:texto.makone="http://schemas.android.com/apk/res-auto"
  tools:context=".MainActivity">
<item
    android:id="@+id/compartirApp"
    android:title="@string/menu_google_App"
    android:icon="@drawable/ic_action_share"
    texto.makone:showAsAction="ifRoom|withText"/>
<item
    android:id="@+id/menuAjustes"
    android:title="@string/menu_ajustes"
    android:icon="@drawable/ic_action_settings"
    texto.makone.:showAsAction="ifRoom|withText"/>
<item
    android:id="@+id/GoogleAppPago"
    android:title="@string/menu_google_App"
    android:icon="@drawable/google_play_icon"
    texto.makone:showAsAction="ifRoom|withText"/>
<item
     android:id="@+id/menuDescripcion"
     android:title="@string/menu_descripcion"
     android:icon="@drawable/google_play_icon"
     texto.makone:showAsAction="never"/>
<item
     android:id="@+id/menuEjemplo"
     android:title="@string/menu_ejemplo"
     android:icon="@drawable/google_play_icon"
     texto.makone:showAsAction="never"/>
 </menu>







texto.makone es el nombre del paquete de mi app y esta linea también es importante : 

xmlns:texto.makone="http://schemas.android.com/apk/res-auto"











Vemos que Descripcion o Ejemplo no aparecen en el Action mientras que los demás están configurados para que sí. Ahora vamos con el tema de la gestión de fragments. Con Android Studio crea el fragment completamente, he creado 2, pero se pueden hacer todos los que se quiera o necesite :




Omito el diseño de los fragments, ya que podeis ver cómo en post como los mencionados anteriormente. Y esta es la clase que por defecto nos crea Android Studio

public class fragmentIntro extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment fragmentIntro.
     */
    // TODO: Rename and change types and number of parameters
    public static fragmentIntro newInstance(String param1, String param2) {
        fragmentIntro fragment = new fragmentIntro();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    public fragmentIntro() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                                      Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_cifrador, container, false);


        return v;
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }
 
    //Comentamos porque sino de momento daría error
    /*@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }*/

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * * See the Android Training lesson Communicating with Other Fragments for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }

}


Aprovechamos y modificamos la función seleccionarFragment para que nos vayamos moviendo por los fragment y vaya cambiando nuestro Action Bar a antojo, según este ejemplo, la opción 1 del drawer nos llevara al fragmentIntro, mientras que las demás nos llevarán al fragmentCifrador. 
Para poder cambiar nuestro Action Bar desde cualquier fragment, que es un problema que me ha llevado un rato, basta con :


this.activity.invalidateOptionsMenu();       //PARA REFRESCAR ACTION BAR JUSTO ANTES DE CREAR EL MENU
this.actionBar = actionBar = ((android.support.v7.app.ActionBarActivity) activity).getSupportActionBar();

//EN CADA FRAGMENT GENERAMOS onCreateOptionsMenu Y AÑADIMOS menu.clear()
public class fragmentIntro extends  Fragment {
  @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
      super.onCreateOptionsMenu(menu, inflater);
      menu.clear();    //Vaciar el menu
      inflater.inflate(R.menu.menu_main, menu);
  }

//EN CADA FRAGMENT GENERAMOS  onActivityCreated Y AÑADIMOS  setHasOptionsMenu(true); 
  @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);
      setHasOptionsMenu(true);        //PARA PODER MODIFICAR EL MENU
   }
}

No os olvideis de poner el número para que entre en el switch del MainActivity, y en la clase configActionBAR(ActionBar menu, int opcion) en el método ClasificarMenu(int opcion) agregar tantos métodos como queramos modificar los Action Bar en cada caso.


  public void instanciarObjetos (){
    contenedorPrincipal=(FrameLayout) findViewById(R.id.contenedor_principal);
    drawerLayout = (DrawerLayout) findViewById(R.id.menu_drawer);

    listaMenu = (ListView) findViewById(R.id.lista_menu);
    listaMenu.setOnItemClickListener(new AdapterView.OnItemClickListener(){
      @Override
        public void onItemClick(AdapterView parent, View view,int position, long id) {
          seleccionarFragment(position);
        }

    });

    View header=getLayoutInflater().inflate(R.layout.header_menu, null); //HEADER
    listaMenu.addHeaderView(header,null,false);

    array = new ArrayList();
    llenarListaMenu(array);

    menuAdapter adaptador = new menuAdapter(this, array);           //ADAPTER
    listaMenu.setAdapter(adaptador);

    //PARA QUE SEA POR DEFECTO EL FRAGMENT INTRO
    seleccionarFragment(1);
    Log.e("MainActivity", "PASOOOOOOOO on CREATE");
  }

  public void seleccionarFragment(int posicion){
      Log.e("MainActivity", "PAS Selecciono fragment"+posicion);
      boolean salida=false;
      android.support.v4.app.Fragment fragment=null;
    switch (posicion) {
      // BOTON PLAY, PRIMERA POSICION = 0
      case 1:
        fragment = new fragmentIntro();
        break;
      case 2:
        fragment = new fragmentCifrador();
        break;
      case 3:
        fragment = new fragmentImagen();
        break;
      case 4:
        fragment = new fragmentCripto();
        break;
      case 5:
        salida=true;

        //MARCAMOS EL CLICKADO
        listaMenu.setItemChecked(posicion, true);
        drawerLayout.closeDrawer(listaMenu);
        finish();
        break;

      default:  Log.e("Main Activity  ", "Opcion  "+posicion);
    }
    //SI SE SALE DE LA APLICACIÓN, AL HACER EL CAMBIO DE FRAGMENT DARIA NULLPOINTEREXCEPTION
    if (salida==false) {
      FragmentManager fragmentManager = getSupportFragmentManager();
      fragmentManager.beginTransaction()
              .replace(R.id.contenedor_principal, fragment)
              .commit();

       listaMenu.setItemChecked(posicion, true);    //MARCAMOS EL CLICKADO
       drawerLayout.closeDrawer(listaMenu);

    }
  }


Si todo ha ido bien, ahora cambiará el estilo de nuestro action Bar y el contenido de los botones que tiene dentro. Ya nos podemos mover por nuestros fragments sin problema. Claro está que en cada recurso menu.xml que hagamos de cada fragmento, nos tocará listar los items, además de asignarles un icono apropiado.









4 Creacción de Swipey tabs en un fragment

Ahora vamos a conseguir un efecto muy chulo en uno de nuestros fragments, en el cifrador en concreto, vamos a insertar unas pestañas que al seleccionar cada una que no sea la misma en donde estamos, la vista se va a "correr" hacia un lado dejando paso a la nueva vista. Creamos 3 fragments más y añadimos a fragmentCifrador.xml el componente ViewPager :


 <android.support.v4.view.ViewPager  
   xmlns:android="http://schemas.android.com/apk/res/android"  
   android:id="@+id/pager"  
   android:layout_width="match_parent"  
   android:layout_height="match_parent"  
    >  
 </android.support.v4.view.ViewPager>




Page Adapter nueva clase
/**
 * Created by makone 
 */
public class PageAdapter extends FragmentPagerAdapter
{
    public PageAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public android.support.v4.app.Fragment getItem(int position) {
        // TODO Auto-generated method stub
        switch (position) {
            case 0:
                return new fragmentNew1();
            case 1:
                return new fragmentNew2();
            case 2:
                return new fragmentNew3();
            default:
                break;
        }
        return null;
    }

    @Override
    public int getCount() {
        return 3;
    }
}

Así que nuestro FragmentCifrador se queda así, claro que hay que crear fragmentNew1, fragmentNew2, fragmentNew3, modificarlos gráficamente y posteriormente ver el efecto. 

Tenemos también que prestar atención al método onDetach(), ya que cada vez que se inicia el fragment, se añaden tabs, es importante que en cada fragment por el que naveguemos lleve las mismas líneas de código en el mismo método onDetach() que a continuación :

package FRAGMENTS.FRAGMENTS_CIFRADOR;

import android.app.Activity;
//import android.app.Fragment;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;

import GESTION.configActionBAR;
import JAVAEE.PageAdapter;
import texto.cifrador.makone.cifradortexto.R;

public class fragmentCifrador extends  Fragment implements android.support.v7.app.ActionBar.TabListener{
  // TODO: Rename parameter arguments, choose names that match
  // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
  private static final String ARG_PARAM1 = "param1";
  private static final String ARG_PARAM2 = "param2";

  // TODO: Rename and change types of parameters
  private String mParam1;
  private String mParam2;

  private OnFragmentInteractionListener mListener;

  public static android.support.v7.app.ActionBar actionBar;
  public configActionBAR CAB;
  Activity host;

  ViewPager viewpager;
  PageAdapter ft;

  // TODO: Rename and change types and number of parameters
  public static fragmentCifrador newInstance(String param1, String param2) {
    fragmentCifrador fragment = new fragmentCifrador();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
  }

  public fragmentCifrador() {
    // Required empty public constructor
  }

  @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);
      setHasOptionsMenu(true);        //PARA PODER MODIFICAR EL MENU
    }

  @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
      }
    }

  @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

      View v = inflater.inflate(R.layout.fragment_cifrador, container, false);
      aniadirTabs(v);

      return v;
    }

  private void aniadirTabs(View v) {
   //RECUPERAMOS CONTEXTO APLICACION
   // host = (Activity) activity.getApplicationContext();
   host = (Activity) v.getContext();
   actionBar = ((ActionBarActivity) host).getSupportActionBar();
   CAB = new configActionBAR(host, 2);
   SacarPestanias (v,host);
 }

  public void SacarPestanias (View v,Activity activity){
    viewpager = (ViewPager) v.findViewById(R.id.pager);
    //ft = new PageAdapter(getSupportFragmentManager());
    //Aqui le añadimos los fragments donde nos queremos mover
    ft = new PageAdapter(((android.support.v7.app.ActionBarActivity) activity)
        .getSupportFragmentManager());
    viewpager.setAdapter(ft);
    actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
    actionBar.addTab(actionBar.newTab().setText("CASAR").setTabListener(this));
    actionBar.addTab(actionBar.newTab().setText("Estadisticas").setTabListener(this));
    actionBar.addTab(actionBar.newTab().setText("Editor").setTabListener(this));

    viewpager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
      @Override
        public void onPageSelected(int arg0) {
                actionBar.setSelectedNavigationItem(arg0);
            }
          @Override
             public void onPageScrolled(int arg0, float arg1, int arg2) {
                // TODO Auto-generated method stub
            }

            @Override
              public void onPageScrollStateChanged(int arg0) {
                // TODO Auto-generated method stub
            }
        });
    }

  @Override
    public void onTabSelected(android.support.v7.app.ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
      viewpager.setCurrentItem(tab.getPosition());
    }

  @Override
    public void onTabUnselected(android.support.v7.app.ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { }

  @Override
    public void onTabReselected(android.support.v7.app.ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { }

  // TODO: Rename method, update argument and hook method into UI event
  public void onButtonPressed(Uri uri) {
    if (mListener != null) {
       mListener.onFragmentInteraction(uri);
    }
  }

  @Override
    public void onAttach(Activity activity) {
      super.onAttach(activity);
      /*  try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");*/
    }

  @Override
    public void onDetach() {
      super.onDetach();
      mListener = null;
      actionBar = ((ActionBarActivity) host).getSupportActionBar();
   actionBar.removeAllTabs();
      actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_STANDARD); //PARA BORRAR PESTAÑERO
    }

  public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    public void onFragmentInteraction(Uri uri);
  }

  @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
      super.onCreateOptionsMenu(menu, inflater);
      menu.clear();
      inflater.inflate(R.menu.menu_cifradores, menu);
    }
}







Podeis descargar el código fuente de thebestandroide con sólo compartir en facebook,twitter,linkedin o suscribirte a nuestro canal RSS más abajo. 



Compartir Compartir Compartir Compartir



Botones dispositivo Android

Blog >Lista Soluciones > Botones dispositivo Android


Tabla de botones fisicos del dispositivo Android




A continuación muestro una tabla con 3 columnas, la primera es el nombre del botón, ya sea del emulador o del dispositivo, la segunda es la tecla rápida a introducir con el teclado del ordenador para el acceso a la función como si se pulsara en el dispositivo virtual, mientras que la tercera nos vale para referenciarla en la programación Java,normalmente en el método onOptionsItemSelected (ej: switch (item.getItemId()) { case android.R.id.home return true;)


Emulated Device Key Keyboard Key KeyEvent
Home HOME  KeyEvent.KEYCODE_HOME
Menu (left softkey) F2 or Page-up button  KeyEvent.KEYCODE_MENU
Star (right softkey) Shift-F2 or Page Down
Back ESC  KeyEvent.KEYCODE_BACK
Call/dial button F3
Hangup/end call button F4
Search F5 KeyEvent.KEYCODE_SEARCH
Power button F7 KeyEvent.KEYCODE_POWER
Audio volume up button KEYPAD_PLUS, Ctrl-F5 KeyEvent.KEYCODE_VOLUMEN_UP
Audio volume down button KEYPAD_MINUS, Ctrl-F6 KEYCODE_VOLUMEN_DOWN
Camera button Ctrl-KEYPAD_5, Ctrl-F3 KeyEvent.KEYCODE_CAMERA
Switch to previous layout
orientation (for example,
portrait, landscape)
KEYPAD_7, Ctrl-F11
Switch to next layout
orientation (for example, portrait, landscape)
KEYPAD_9, Ctrl-F12
Toggle cell networking on/off F8
Toggle code profiling F9 (only with -trace
startup option)

Toggle fullscreen mode Alt-Enter
Toggle trackball mode F6
Enter trackball mode temporarily
(while key is pressed)
Delete
DPad left/up/right/down KEYPAD_4/8/6/2 KeyEvent.KEYCODE_DPAD_UP,
KeyEvent.KEYCODE_DPAD_DOWN,
KeyEvent.KEYCODE_DPAD_LEFT,
KeyEvent.KEYCODE_DPAD_RIGHT
DPad center click KEYPAD_5 KeyEvent.KEYCODE_DPAD_CENTER
Onion alpha increase/decrease KEYPAD_MULTIPLY(*) / KEYPAD_DIVIDE(/)



Teclado Numérico
 KeyEvent. – KEYCODE_0,  KEYCODE_1,  KEYCODE_2, … ,  KEYCODE_9 , KEYCODE_A, … , KEYCODE_Z
Botón de medios
KEYCODE_HEADSETHOOK











Compartir Compartir Compartir Compartir



Styleguide de Google para programar en Android.

Blog >Lista Soluciones > Estándares Android





Estándares de Google para Android


Definición de estándar 

Un estándar de programación es una forma de "normalizar" la programación para que al trabajar en un proyecto cualquiera, las personas involucradas en el mismo tengan un acceso rápido y una correcta comprensión del código. Un estándar nos define la escritura y organización del código fuente de un programa, además el seguir un estándar de programación te facilita como programador la modificación de tu propio código fuente aunque lleves tiempo sin mirarlo.







El pasado año 2014, google sacó un artículo en el que definía unos estándares con los que programan ellos en Android, el artículo lo podeis ver aquí .

Así que los he agrupado y aunque no todos, están los más comunes que usamos a la hora de programar. Además si también si quereis ver los estándares de java más comunes podreis echar un vistazo aquí.


Comentarios 

Si los comentarios que tratan sobre implementaciones o comentar el código serán los comentarios de implementación. Comentarios de bloque, estos van arriba en la clase, precedidos de linea en blanco :

/**
 * @author makone
 * @description This class creates a Noticia object
 */

Comentarios de línea : Comentarios cortos alineados al mismo nivel de la linea de código que sigue. Llevan linea en blanco :

   
try {
  //ACCION
  } catch (Exception e) {
    Log.e("Error", e.getMessage());
    e.printStackTrace();
  }
 

Comentarios de aclaración : Comentarios en la misma linea del código comentado, si hay más de uno, intentar alinear aunque no es obligatorio.

 private int id;
 private int categoria;
 
 private String name;            //titulo principal
 private String descripcion;
 private String URLimagen;       //URL para descargar imagen


La extructura

La extructura de bloques tiene que llevar el estilo K & R ("Egyptian brackets") :

return new MisPeliculas() {
  @Override public void method() {
    if (condition()) {
      try {
        something();
      } catch (ProblemException e) {
        recover();
      }
    }
  }
};

La indentación

La indentación (la tabulación entre distintos niveles) es de 2 espacios y sólo habrá una sentencia por línea.

La llave de apertura { nunca estará precedida de linea en blanco y lo siguiente será un salto de linea.

Salto de línea después de la llave de cierre }, e intentar alinearla con la línea donde se abrió ese bloque. No hay salto de linea despues de la linea si es seguido por otra llave o una coma.

Los bloques vacíos tendrán este formato

//Constructor 1
void doNothing() {}

Límite de línea

Cualquier proyecto puede elegir tener el límite de la columna 80 a la 100.

Cuando una misma línea se divide en varias líneas, normalmente para evitar que desborda el límite de la columna, esta actividad se llama ajuste de líneas.que son sangría de 4 espacios. Cuando hay múltiples líneas de continuación, la sangría se puede variar más allá de 4 como se desee. En general, dos líneas de continuación utilizan el mismo nivel de sangrado si y sólo si comienzan con elementos sintácticamente paralelos.

//EJEMPLO 1
public producto(int id, String nombre,float precio, String descripcion,String uRLimagen,  
    int cat) {
  this.precio = precio;
  this.id = id;
  this.nombre = nombre;
  this.descripcion = descripcion;
  this.URLimagen = uRLimagen;
  this.cat = cat;
}
 
//EJEMPLO 2
public boolean checkConnectivity() {
  boolean enabled = true;   
  ConnectivityManager connectivityManager = (ConnectivityManager) this.c
     .getSystemService(Context.CONNECTIVITY_SERVICE); 
  
  NetworkInfo info = connectivityManager.getActiveNetworkInfo();          
  if ((info == null || !info.isConnected() || !info.isAvailable())){
 enabled = false;
  }
  return enabled;        
}


Líneas en blanco

Entre los miembros consecutivos (o inicializadores) de una clase como pueden ser campos, constructores, métodos, clases anidadas, inicializadores estáticos o inicializadores de instancia. 

Además dentro de cuerpos de los métodos, según sea necesario para crear agrupaciones lógicas de declaraciones.

         
 String id =        c.getString("ID");
 String name =      c.getString("NAME");
 String desc =      c.getString("DESCRIPCION");
 String imagen =    c.getString("IMAGE");
 String precio =    c.getString("PRECIO");
 String categoria = c.getString("CATEGORIA");
 
 e=new producto();
 e.setId(Integer.valueOf(id));
 e.setNombre(name);
 e.setdescripcion(desc);
 e.setPrecio(Float.parseFloat(precio));
 e.setURLimagen(imagen);
 e.setCat(Integer.valueOf(categoria));

Espacios en blanco

Habrá espacios detrás de cada if, for o catch Antes de cualquier llave de apertura { [ con dos excepciones, una son las anotaciones y otras como por ejemplo los arrays:

String[][] x = {{"foo"}};

A ambos lados de cualquier operador binario o ternario,y también se aplica : En multiples excepciones

    catch (FooException | BarException e)


  • En el foreach :


public boolean cargaFotosNoticiasAcabada(ArrayList no){
  for (Object noticia : no){
 producto pas = (producto) noticia;
   if (pas.isFotoCargada()==false){
     return false;
   }
  }
  return true;
}


  • Después de , : ; o al cerrar un paréntesis y al agrupar elementos por ejemplo :

 
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }

Opcional : justo dentro de las dos llaves de una inicialización de un array
 
new int[] {5, 6} and new int[] { 5, 6 } da igual una que otra.


Extructuras formales de inicialización de un array 


 
new int[] {           new int[] {
  0, 1, 2, 3            0,
}                       1,
                        2,
new int[] {             3,
  0, 1,               }
  2, 3
}                     new int[]
                          {0, 1, 2, 3}


Atributos de clase, métodos y variables : aparecen en el orden recomendado por la especificación del lenguaje Java:

public protected private abstract static final transient volatile synchronized native strictfp


Los nombres de las clases seguiran este formato : UpperCamelCase, con verbos adecuados
CONSTANTES : Siempre con mayúsculas

// Constants
static final int NUMBER = 5;
static final ImmutableList NAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(',');  // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }

VARIABLES : Siempre empiezan con letra pequeña :

// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set mutableCollection = new HashSet();
static final ImmutableSet mutableElements = ImmutableSet.of(mutable);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};

Excepciones : Queda prohibido hacer una excepción en la que no haya nada que mostrar cuando salte. Para las pruebas usaremos NoSuchElementException para averiguar que excepción se produce.

try {
  emptyStack.pop();
  fail();
} catch (NoSuchElementException expected) {
}





Compartir Compartir Compartir Compartir