• THE BEST ANDROIDE

    Este blog está orientado para aquellos desarrolladores especializados en Android. Todo el contenido está en base de aquellos errores que me he ido encontrando y a la vez, posteando las soluciones, ya que de momento para varios problemas específicos, todavía falta documentación en la red.

    Espero que sea de ayuda para todos los Android developers.

  • CONTACTO

    Si eres de alguna empresa, con hacer click en la imagen, podrás descargar mi curriculum.

  • BOXING CLOCK

    Marca el tiempo de entrenamiento de boxeo. Se repite cada tres minutos incluyendo un minuto de descanso, pudiendo ser muy útil para practicar boxeo al aire libre sin necesidad de programar ninguna alarma cada tres minutos.

    Si llevas un gimnasio con enchufar un cable de audio en una cadena de música, no tendrás necesidad de comprar un cronómetro de entrenamiento de boxeo ¡ya lo tienes en tu móvil!

  • DEVELOPER MOBILE

    “Cualquier tonto puede escribir código que un ordenador entiende. Los buenos programadores escriben código que los humanos pueden entender.”

    Martin Fowler.

Blog cerrado

ESTAMOS cerrando el blog, en un periodo de tiempo dejaremos de escribir entradas ya que estamos modelando la migracion del blog a liferay, donde dedicare una sección a Android. Sigo dejandolo publico para que podais descargar código, ya que la idea inicial era compartir codigo e ideas con la cominidad java, especificamente Android.

Salu2!

Android : Dialog con Pager dentro



View Pager dentro DialogFragment

Buenas developers, en esta ocasión vamos a combinar un Dialog con un View Pager. Este tipo de combos los podemos usar para desarrollar tutoriales dentro de nuestras aplicaciones entre otras cosas.

Antes de empezar quiero destacar que la implementación de la librería android.support.v4.app es una chapuza de las más grandes de Android, y todo por la maldita fragmentación, así que en este caso voy a poner todos los imports de las clases para que no haya confusión ante las librerías que usan los objetos.

Comenazmos creando 2 fragments : fragmento y fragmento2 :






import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
public class fragmento extends Fragment {
 
    private OnFragmentInteractionListener mListener;

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

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragmento, container, false);
    }

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

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


import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class fragmento2 extends Fragment {

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragmento2, container, false);
    }

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

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


Y ahora vamos con el DialogFragment, que es quien va a contener el pager, con su correspondiente adaptador :





import android.app.Dialog;
import android.support.v4.app.DialogFragment;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;


/**
 * Created by makone on 16/03/2015.
 */
public class fragmentDialogo extends DialogFragment{

  private PageAdapter PagAdapter; //ADAPTADOR
  private ViewPager viewPager;

  @Override
    public Dialog onCreateDialog(final Bundle savedInstanceState) {
      Dialog dialog = super.onCreateDialog(savedInstanceState);
      //Configuracion Dialog
      dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
      dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
      return dialog;
    }

  @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      View view = inflater.inflate(R.layout.fragment_dialog, container);   //INFLAMOS CON LA VIEW
      android.support.v4.app.FragmentManager fm = getChildFragmentManager();
      PagAdapter = new PageAdapter(fm);                              //CREAMOS ADAPTER
      viewPager = (ViewPager)view.findViewById(R.id.pager);          //INICIAMOS PAGER
      viewPager.setAdapter(PagAdapter);                              //APLICAMOS ADAPTER AL PAGER

      return view;
    }
}


import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
 
public class PageAdapter extends FragmentPagerAdapter {

  public PageAdapter(FragmentManager fm) {
        super(fm);
    }

  @Override
    public android.support.v4.app.Fragment getItem(int position) {
      if (position == 0) {
        // find first fragment...
        fragmento ft1 = new fragmento();
        return ft1;
      }

      if (position == 1) {
        // find first fragment...
        fragmento2 ft2 = new fragmento2();
        return ft2;
      }

      return null;
    }

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


Bien, ya está todo montado, solo falta nuestra actividad principal crear un botón para llamar al Dialog con el pager cargado :




import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.view.View;
import android.widget.Button;

public class MainActivity extends FragmentActivity {
  private Button boton;
  @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      boton = (Button) findViewById(R.id.botonAction);   //REFERENCIA AL BOTON
      boton.setOnClickListener(new View.OnClickListener() {
        @Override
          public void onClick(View v) {
                openDialog(v);
          }
      });
    }

  public void openDialog(View view) {
    FragmentManager fm = getSupportFragmentManager();
    fragmentDialogo overlay = new fragmentDialogo();
    overlay.show(fm, "FragmentDialog");
  }
}


Y este es el resultado :






Compartir Compartir Compartir Compartir

Intents en Android

Tipos y uso de intents




Buenas developers, a continuación aumento el repositorio de código con un tema bastante sencillo, los intents.

Vamos a ver una serie de intents "curiosos" que nos aportarán funcionalidades distintas. Empezamos por el más básico, cambio de actividad con el paso de parámetros, en un proyeco en blanco, he creado 2 actividades :





public class MainActivity extends Activity {

  int numero    = 8;
  String cadena = "Blog ThebestAndroide";

  private Button boton;

  @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      //REFERENCIA BOTON
      boton = (Button) findViewById(R.id.button);
      boton.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              lanzarIntent1(MainActivity.this, cadena, numero);
          }
      });
    }

  public static void lanzarIntent1(Activity activity, String cadena, int numero) {
    String NombreActivity = "segundaActivity";
    Intent intent = new Intent(NombreActivity);
    Bundle bundle = new Bundle();
    bundle.putInt("NUMERO", numero);
    bundle.putString("CADENA", cadena);
    intent.putExtras(bundle);

    activity.startActivity(intent);
  }
}

public class Activity2 extends Activity {

  @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_activity2);

      TextView text1, text2;

      //REFERENCIA OBJETOS XML
      text1 = (TextView) findViewById(R.id.textView2);
      text2 = (TextView) findViewById(R.id.textView3);

      //RECOGER PARÁMETROS
      Bundle extras = getIntent().getExtras();
      if (extras != null) {
        String cadena = extras.getString("CADENA");
        int numero = extras.getInt("NUMERO");
        if (cadena != null) {
          text1.setText("Variable Int : " + numero);
          text2.setText("Variable String : " + cadena);
        }
      }
    }
}






Observamos que la variable NombreActivity tiene el mismo nombre que le ponemos en la etiqueta intent del androidManifest, en el ejemplo hemos pasado 2 tipos de datos en el intent primitivos, ¿Sencillito no? ahora bien, veremos como pasar un objeto. 





¿Cómo pasamos un objeto por medio de un intent?

Podríamos serializar una clase por medio de una interfaz serializable, pero este proceso en Android supone un problema de rendimiento

Para eso usamos la interfad Parcelable, que es específica para serializar objetos y moverlos de actividad a actividad. Así que modificamos nuestro Javabeans para que podamos serializar los objetos.

package intents.thebestandroide.intents;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by makone on 15/03/2015.
 */
public class producto implements Parcelable {
    int id;
    String name;
    String descripcion;

    public producto() {
    }

    public producto(int id, String name, String descripcion) {
        this.id = id;
        this.name = name;
        this.descripcion = descripcion;
    }

    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 getDescripcion() {
        return descripcion;
    }

    public void setDescripcion(String descripcion) {
        this.descripcion = descripcion;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public producto (Parcel parcel){
        readToParcel(parcel);
    }

    public static final Parcelable.Creator CREATOR =
            new Parcelable.Creator() {
                public producto createFromParcel(Parcel source) {
                    return new producto(source);
                }
                public producto[] newArray(int size) {
                    return new producto[size];
                }
    };

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(id);
        out.writeString(name);
        out.writeString(descripcion);
    }

    public void readToParcel(Parcel parcel){
        id = parcel.readInt();
        name = parcel.readString();
        descripcion = parcel.readString();
    }
}

Y en nuestras dos activity, cambiamos el código referente a las variables :

public class MainActivity extends Activity {
  private Button boton;

  @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      //REFERENCIA BOTON
      boton = (Button) findViewById(R.id.button);
      boton.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              lanzarIntent1(MainActivity.this);
          }
      });
    }

  public static void lanzarIntent1(Activity activity) {
    String NombreActivity = "segundaActivity";
    Intent intent = new Intent(NombreActivity);

    producto p = new producto();
    p.setId(1);
    p.setName("makone");
    p.setDescripcion("thebestAndroide");

    //Insertamos objeto
    intent.putExtra("producto",p);

    activity.startActivity(intent);
  }
}


public class Activity2 extends Activity {

  @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_activity2);

      TextView text1, text2, text3;

      //REFERENCIA OBJETOS XML
      text1 = (TextView) findViewById(R.id.textView2);
      text2 = (TextView) findViewById(R.id.textView3);
      text3 = (TextView) findViewById(R.id.textView4);

      //RECOGER PARÁMETROS
      Bundle extras = getIntent().getExtras();
      producto p = extras.getParcelable("producto");

      if (extras != null) {
         int numero    = p.getId();
         String nombre = p.getName();
         String desc   = p.getDescripcion();

         text1.setText("Id : " + numero );
         text2.setText("Nombre : " + nombre );
         text3.setText("Descripcion : " + desc );
      }
    }
}




Bien, ahora que ya hemos visto cómo hacer un intent simple con parámetros primitivos, además de un paso de objeto (el paso de arraylist lo he omitido porque para algo se crearon las BBDD) , ahora vamos a ver diversos intents curiosos que aportan funcionalidades distintas :

Abrir dirección web

//la url debe incluir siempre el protocolo
  public static void lanzarIntent1(Activity activity) {
    String url = "http://www.google.es";
    activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
  }





Buscar en Youtube con la app oficial 

  public static void lanzarIntent1(Activity activity) {
    Intent intent = new Intent(Intent.ACTION_SEARCH);
    intent.setPackage("com.google.android.youtube");
    //CADENA PARA BÚSQUEDA
    intent.putExtra("query", "zenet soñar contigo");
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    try{

      activity.startActivity(intent);
      } catch (ActivityNotFoundException e) {
        //la app no está instalada
        System.out.println("App youtube no instalada");
      }
    }


Abrir aplicación Google Play con el id de la app
 
  public static void lanzarIntent1(Activity activity) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setData(Uri.parse("market://details?id=cronometroboxeo.com"));
    try {
      activity.startActivity(intent);
    } catch (android.content.ActivityNotFoundException e) {
      //SI HA DADO EXCEPCION PORQUE EL MARKET NO ESTA DISPONIBLE, ABRIMOS NAVEGADOR CON LA RUTA DE LA APP INTERESADA
      activity.startActivity(new Intent(Intent.ACTION_VIEW,
    Uri.parse("https://play.google.com/store/apps/details?id=cronometroboxeo.com")));
      System.out.println("Market no disponible");
    }
  }




Buscar en Google
 
  public static void lanzarIntent1(Activity activity) {
    Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
    intent.putExtra(SearchManager.QUERY, "Thebestandroide");
    activity.startActivity(intent);
  }




Compartir / enviar

public static void lanzarIntent1(Activity activity) {
  Intent intent = new Intent(android.content.Intent.ACTION_SEND);
  intent.setType("text/plain");
  intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Asunto"); 
  intent.putExtra(Intent.EXTRA_TEXT, "Contenido mensaje");
  activity.startActivity(Intent.createChooser(intent, "Compartir usando"));
}




Enviar E-mail
 
  public static void lanzarIntent1(Activity activity) {
    Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:mail@gmail.com"));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "body");
    activity.startActivity(Intent.createChooser(emailIntent, "Seleccione una aplicación"));
  }

Agregar contactos 
 
  public static void lanzarIntent1(Activity activity) {
    Intent contactIntent = new Intent(Intent.ACTION_INSERT);
    contactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE);
    contactIntent.putExtra(ContactsContract.Intents.Insert.NAME,"Peter Parker");
    contactIntent.putExtra(ContactsContract.Intents.Insert.EMAIL,"mail@mail.com");
    contactIntent.putExtra(ContactsContract.Intents.Insert.PHONE,"11-7-666-23");
    activity.startActivity(contactIntent);
  }


Guardar en gestores de eventos
 
  public static void lanzarIntent1(Activity activity) {
    Intent intent = new Intent(Intent.ACTION_EDIT);
    intent.setType("vnd.android.cursor.item/event");
    intent.putExtra("allDay", false);
    intent.putExtra("title", "Cita Laura");
    intent.putExtra("description", "Llevar preservativos por si se deja...");
    activity.startActivity(Intent.createChooser(intent, "Seleccione una aplicación"));
  }
 

Reproducir multimedia
 
Hay que procurar indicar el MimeType correcto, vamos el formato según el tipo al que queramos acceder.Puede ser una url remota o un archivo : (file:///sdcard/MUSICA/song.mp3)
 
    public static void lanzarIntent1(Activity activity) {
      Intent intent = new Intent(Intent.ACTION_VIEW);
      intent.setDataAndType(Uri.parse("http://dominio.com/song.mp3"),"audio/mpeg");
      activity.startActivity(intent);
    }


Hacer una llamada
 
Hay que especificar, que para nuestras aplicaciones, en el caso que necesitemos hacer una llamada, para evitar poner el permiso en la app de que esta pueda llamar, usamos ACTION.DIAL.

    //ACTION DIAL NO REQUIERE CALL_PHONE
    public void HacerLLamada(){
      try {
      Intent callIntent;
      callIntent = new Intent(Intent.ACTION_DIAL);
      Resources res = getResources();
      //String text = String.format(res.getString(R.string.telefono)); //PARA TELF EN STRING
      String text = "tel:555-555-555";
      Log.e("formato  llamada ::: ", text.toString());
      callIntent.setData(Uri.parse("tel:"+text));
      startActivity(callIntent);
      } catch (ActivityNotFoundException activityException) {
        Log.e("dialing-example", "Llamada fallida", activityException);
      }
    }  








Compartir Compartir Compartir Compartir

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