Un Action Provider es un elemento que habita en la Action Bar para incrementar la accesibilidad de nuestras aplicaciones. Este View tiene como fin recibir eventos del usuario como si se tratase de un action button , pero con un alcance más complejo como el despliegue de menús y otros widgets.
Aunque podemos crear nuestros propios Action Providers, este articulo cubre el uso de un tipo ya prefabricado, llamado ShareActionProvider.
Qué es un ShareActionProvider en Android
La función de esta clase es proveer a la aplicación de una opción para compartir el contenido de nuestra aplicación. Frecuentemente se suele ubicar en las galerías de imágenes y así enviarlas a otras personas por diferentes servicios como Bluetooth, Mensajería, Google+, Facebook, Twitter, etc.
Para comprender como implementar uno de estos crearemos el siguiente ejemplo:
Ejemplo de un ShareActionProvider
Este ejemplo se le ha denominado «Joky» y su objetivo es permitir compartir a través de un ShareActionProvider chistes que se encuentran predefinidos en la aplicación. Puedes descargar el código completo del proyecto desde aquí:
A continuación se muestran los pasos a seguir para implementar la aplicación.
Paso 1: Crear un nuevo proyecto en blanco.
Lo primero es crear un nuevo proyecto en blanco con una actividad principal llamada Main.java y su respectivo archivo de diseño activity_main.xml. También es necesario añadir una dependencia de la librería de soporte v4.
Paso 2: Declarar el Action Provider en la Action Bar
Abre el menu con el cual inflarás la Action Bar de la actividad (si se ha generado automáticamente se llamará menu_main.xml) y luego declara un elemento tipo <item>. Para indicar que este item será inflado con un ShareActionProvider, debes usar el atributo support:actionViewclass y asignar la ubicación de la clase en la librería de soporte v7:
//Archivo menu_main.xml <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:support="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_share" android:title="@string/menu_share" support:actionProviderClass="android.support.v7.widget.ShareActionProvider" support:showAsAction="always" /> </menu>
Ahora, si quieres manipular el ShareActionProvider a través de toda la actividad, declara una instancia global dentro de Main:
// Referencia global del ShareActionProvider private ShareActionProvider shareAP;
Paso 3: Añadir un ViewPager para efecto deslizante
Para la navegación usaremos un ViewPager que permita al usuario deslizar la visualización entre elementos. Así que reemplaza el contenido predeterminado de activity_main.xml por un layout que contenga un nodo raíz de tipo <android.support.v4.view.ViewPager>. Veamos:
// Archivo activity_main.xml <?xml version="1.0" encoding="utf-8"?> <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent"/>
Paso 4: Crear un Origen de datos para alimentar el Adaptador del ViewPager
Recuerda que un ViewPager necesita un PagerAdapter para poblar sus items. En la aplicación Joky cada uno de estos items será un TextView. Su contenido se obtendrá de 5 cadenas guardadas en el archivo strings.xml.
// Arhivo strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Joky</string> <string name="menu_share">Compartir</string> <string name="joke1"> - ¡Maestra! ¡Un niño se ha caído de la ventana!\n - ¡Qué horror!!!!? Se dice "por la ventana" </string> <string name="joke2"> - Mamá, ¿qué haces en frente de la computadora con los ojos cerrados?\n - Nada, hijo, es que Windows me dijo que cerrara las pestañas?</string> <string name="joke3"> - Papá, ¿qué se siente tener un hijo tan guapo?\n - No sé hijo, pregúntale a tu abuelo? </string> <string name="joke4"> - Mamá, mamá, en el colegio me dicen champú\ - Tranquilo, Johnson, no más lágrimas. </string> <string name="joke5"> - Capitán, ¿Puedo desembarcar por la izquierda?\n ? Se dice por babor?\n ? Por babor Capitán, ¿Puedo desembarcar por la izquierda? </string> </resources>
Para representar la asociación de cada item a las cadenas, simplemente creas una nueva clase que enfrasque estas características. Dicha clase se llamará ContentItem y tendrá como atributo el identificador del string y un método para compartir su contenido.
Veamos:
// Archivo ContentItem.java public class ContentItem { public final int idString; public ContentItem(int idString) { this.idString = idString; } public Intent getShareIntent(Context context) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, context.getString(idString)); return intent; } }
Retomemos. El propósito de Joky es enviar chistes hacia otras aplicaciones capaces de compartirlos. Tu ya sabes que este tipo de comunicación entre actividades se genera a través de Intents (Lee también Comunicar Actividades a través de Intents).
El método getShareIntent() fabrica el Intent de envío de cada string en nuestro ViewPager. Por esta razón el método retorna en un tipo Intent. Al crear el item se usa la acción ACTION_SEND para indicar que será un intent implícito que congregará aplicaciones de envío de datos.
Luego se indica que enviaremos texto plano («text/plain») y finalmente se incluye un valor extra marcado con la clave EXTRA_TEXT. Esta clave representa la estructura de la cadena y debe enviarse junto al valor que se obtiene con getString() de la clase Context (se recibe una instancia como parámetro).
Lo siguiente es crear una lista de ContentItems dentro de Main para poblar el View Pager:
private final ArrayList items = getContent();
Si notas, se usa el método getContent() para la inicialización de los elementos:
/* Método para inicializar la lista de items */ static ArrayList getContent() { ArrayList items = new ArrayList(); items.add(new ContentItem(R.string.joke1)); items.add(new ContentItem(R.string.joke2)); items.add(new ContentItem(R.string.joke3)); items.add(new ContentItem(R.string.joke4)); items.add(new ContentItem(R.string.joke5)); return items; }
Paso 5: Declarar un PagerAdapter personalizado para el ViewPager
Al querer mostrar cada chiste en una página individual del ViewPager es necesario sobrescribir la clase PagerAdapter para que infle Text Views que ocupen el contenido.
Así que lo primero que tienes que hacer es diseñar el layout para los items del pager:
// Archivo item_text.xml <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" android:textAppearance="?android:textAppearanceMedium" android:lineSpacingMultiplier="1.1" android:gravity="center_vertical" />
Como ves, cada item es un elemento <TextView> como nodo raíz.
Ahora procedemos a crear una clase anónima dentro de Main para el PagerAdapter:
/* Adaptador del ViewPager */ private final PagerAdapter adapter = new PagerAdapter() { LayoutInflater inflater; @Override public int getCount() { return items.size(); } @Override public boolean isViewFromObject(View view, Object o) { return view == o; } @Override public void destroyItem(ViewGroup container, int position, Object object) { // Remover item container.removeView((View) object); } @Override public Object instantiateItem(ViewGroup container, int position) { // Evitar infladas de más if (inflater == null) { inflater = LayoutInflater.from(Main.this); } // Obtener item actual final ContentItem item = items.get(position); // Inflar el item con item.text.xml TextView tv = (TextView) inflater .inflate(R.layout.item_text, container, false); // Asignar la cadena correspondiente tv.setText(item.idString); // Añadir View al Pager container.addView(tv); return tv; } };
Si ya antes has implementado tu propio PagerAdapter sabes que tenemos una extensión realmente sencilla. La verdadera magia está en el método instantiateItem(), el cual infla todas los elementos con el layout item_text.xml y setea el contenido de los Text Views con el método setText() que recibe el identificador de la cadena.
Paso 6: Implementar los eventos con OnPageChangeListener
Cada que un elemento de la lista es seleccionado en el ViewPager se debe actualizar el contenido que se va a enviar. Esto quiere decir que debemos realizar toda nuestra acción en el método onPageSelected(). El ShareActionProvider activa su comportamiento cuando le asignamos una instancia del Intent que contiene la información a trasmitir con el método setShareIntent().
Por esta razón obtendremos el elemento del viewpager seleccionado y retornaremos en su intent con el método getShareIntent().
/* Escucha del ViewPager */ private final ViewPager.OnPageChangeListener listener = new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // Nada por hacer } @Override public void onPageSelected(int position) { if (shareAP != null) { // Obtener el item actual y su Intent para envío ContentItem item = items.get(position); Intent shareIntent = item.getShareIntent(); // Actualizar el shareAP con el intent de envío shareAP.setShareIntent(shareIntent); } } @Override public void onPageScrollStateChanged(int state) { // Nada por hacer } };
La implementación del menú desplegable y los eventos de clics sobre cada opción del provider, no se tienen que implementar, así que despreocupate por la sobrescritura del método onOptionsItemSelected() para la action bar y la implementación del menú.
Paso 7: Implementar el método onCreate() de la actividad principal
El siguiente paso es inflar la actividad principal y obtener una instancia del ViewPager para relacionarle su adaptador y escucha.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Inflar actividad setContentView(R.layout.activity_main); // Obtener instancia del viewpager ViewPager vp = (ViewPager) findViewById(R.id.viewpager); // Relacionar escucha vp.setOnPageChangeListener(listener); // Relacionar adaptador vp.setAdapter(adapter); }
Y por ultimo debes obtener la instancia del ShareActionProvider en el método onCreateOptionsMenu(). También aprovecha para inicializar por defecto el primero elemento del ViewPager, es decir, preasignarle el primer intent que contenga los datos del primer chiste. Veamos:
@Override public boolean onCreateOptionsMenu(Menu menu) { // Inflar la action bar getMenuInflater().inflate(R.menu.menu_main, menu); // Obtener el item que contiene el share action provider MenuItem shareItem = menu.findItem(R.id.menu_share); // Copiar la referencia del objeto ShareActionProvider del item shareAP = (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem); // Establecer por defecto el elemento 0 del viewpager // para inicializar su share action provider ContentItem item = items.get(0); Intent shareIntent = item.getShareIntent(); shareAP.setShareIntent(shareIntent); return super.onCreateOptionsMenu(menu); }
Si no declaras por defecto el primer elemento que se va a inflar , entonces el ShareActionProvider no mostrará ninguna respuesta ante el usuario a menos que vayas a el segundo item y te devuelvas.
Y ya para finalizar este tutorial, ejecuta y prueba tu aplicación Joky:
Autor: James Revelo
Web: http://www.hermosaprogramacion.com/
Dando respuesta a una interrogante sobre el como crear objetos en tiempo de ejecución y como manipular estos, desarrolle[...]
En este post veremos un ejemplo de como comprimir y descomprimir archivos con el método de compresión GZIP y el pa[...]
En este post aprenderemos a usar los gráficos 2d que viene con JavaFX en nuestras aplicaciones java swing. Esto puede se[...]
Hace tiempo me pidieron el código fuente de un juego de Puzzle de Neon Genesis Evangelión, este juego es completo, tiene[...]
Si quieres cambiar el nombre de tus atributos sin tener que reescribir código java por X o Y razón, GSON te permite reno[...]
Me llego la siguiente duda por facebook que me pareció interesante: «Se quiere desarrollar una tabla en java que haga us[...]