«

»

nov 03 2011

ViewPager: Implementando columnas

Si hay algo que me encanta de Android es la infinidad de elementos de interfaz que existen, si no es por parte de la propia SDK es por las librerias que muchos cracks se curran. Entre estos elementos hay uno que me gusta a rabiar ya que bien usado proporciona una usabilidad a nuestras aplicaciones que de otra manera decreceria mucho. Este elementos son las columnas/paginas de desplazamiento horizontal que ya podemos ver en aplicaciones como el nuevo Android Market o desde hace mucho mas tiempo en TweetDeck. Si como yo estais deseando de incluir este elemento en vuestras aplicaciones no dudes en seguir leyendo y enterarte como.

 

 

La vista que implementa esta funcionaidad se ViewPager y fue lanzada con el Compatibility Package, así que lo primero que debemos hacer es asegurarnos que lo tenemos descargado para usarlo y en caso negativo descargarlo. Para ello desde eclipse o directamente accedemos al Android SDK Manager y buscamos el paquete Android Support package. Desde aqui podremos comprobar si esta instalado y si no fuera asi instalarlo.

 

 

Una vez que nos hemos asegurado de que disponemos de la libreria deberemos añadirla a nuestro proyecto, para ello creamos una carpeta /libs a la misma altura que la carpeta /src y copiamos en ella el archivo android-support-v4.jar que encontraremos en ..Androidandroid-sdkextrasandroidsupportv4. Una vez copiado pulsamos sobre el con el boton derecho de nuestro raton (en eclipse) y hacemos click sobre Build Path >> Add to Build Path.

 

 

Con esto ya podremos usar la libreria desde nuestro proyecto, así que vamos a lo interesante.

 

Como cualquier otra vista la deberemos añadir a nuestros layouts de la manera que mas se adapte a nuestras necesidades pero con la salvedad de que al no ser nativa del SDK de Android deberemos referenciarla con el nombre completo de la clase que la implementa, incluyendo el nombre del paquete. Quedaria algo asi:

 

<android.support.v4.view.ViewPager
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       … />

 

ViewPager es un ViewGroup y funciona de manera similar a los AdapterViews (como los ListView o Gallery), así que no nos enfrentaremos a un problema completamente nuevo. En la Activity en cuestion en la que implementemos nuestro paginado bastara con recuperar la vista ViewPager y asignarle el Adapter que nosostros mismos implementaremos y que heredara de PageAdapter.

 

public class ColumnasActivity extends Activity {
    private ViewPager columnas;
    private static int NUM_COLUMNAS = 3;
    private Context cxt;
    private ColumnasAdapter miAdapter;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        cxt = this;

        miAdapter = new ColumnasAdapter();
        columnas = (ViewPager) findViewById(R.id.columnas);
        columnas.setAdapter(miAdapter);
    }

    private class ColumnasAdapter extends PagerAdapter {
    ...

 

Así que los nos queda será implementar nuestro adapter que ira suministrando las paginas a nuestro ViewPager diseñadas y almacenadas en layouts. Podríamos generar las pagina por código como es el caso del ejemplo que os enlazamos al final del post, pero en el siguiente codigo os mostramos como hacerlo si queremos diseñar nuestras paginas directamente en layouts en xml.

El metodo getCount es el que se encarga de devolver el numero de paginas que se mostraran, mientras que instantiateItem nos devolvera cada pagina a mostrar.

Es importante asegurar que en destroyItem y isViewFromObject el casteo esta implementado correctamente.

 

    private class ColumnasAdapter extends PagerAdapter {

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

        @Override
        public Object instantiateItem(View collection, int position) {
            LinearLayout v = (LinearLayout) LayoutInflater.from(cxt).inflate(R.layout.columna1, null);
           
            if (position == 0) {
                v = (LinearLayout) LayoutInflater.from(cxt).inflate(R.layout.columna1, null);
            } else if (position == 1) {
                v = (LinearLayout) LayoutInflater.from(cxt).inflate(R.layout.columna2, null);
            } else {
                v = (LinearLayout) LayoutInflater.from(cxt).inflate(R.layout.columna3, null);
            }
           
            ((ViewPager) collection).addView(v, 0);

            return v;
        }

       
        @Override
        public void destroyItem(View collection, int position, Object view) {
            ((ViewPager) collection).removeView((LinearLayout) view);
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == ((LinearLayout) object);
        }

        @Override
        public void finishUpdate(View arg0) {
        }

        @Override
        public void restoreState(Parcelable arg0, ClassLoader arg1) {
        }

        @Override
        public Parcelable saveState() {
            return null;
        }

        @Override
        public void startUpdate(View arg0) {
        }
    }
}

 

Para incluir mas paginas bastara con que cambieis el valor NUM_COLUMNAS y añadais mas archivos de layouts. Pero esta parte de la implementacion no es fija, si no que en funcion de nuestras necesidades podemos buscar nuevas formas de implementar nuestro Adapter para que se ajuste a nuestras necesidades, lo unico importante es que finalmente proporcione la vista que se ira a mostrar en cada caso.

Ademas de PagerAdapter disponemos de otras implementaciones como FragmentagerAdapter o FragmentStateAdapter, ambas usan Fragments en vez de vistas como el caso anterior. La diferencia entre ambas es que la primera mantiene todas las paginas en memoria y la segunda en cambio no, esto conllevaria la recarga de cada pagina cada vez que nos movemos a traves de ellas, pero si nos encontramos antes un caso con muchas paginas puede que esta opcion sea la acertada.

 

Con esto hemos concluido el tutorial que espero os sirva de ayuda.
 

Fuente | Android Developers
Ejemplo | Google Code

 

Acerca del autor

JMPergar

Mobile Developer at @BeRepublic & Founder of @AndroCode. Silver Speaker & Member of Core Team at @GDGBarcelona.

  • Juan Carlos

    Muy bueno, Gracias

    • http://hackedbrain.blogspot.com/ JMPergar | Editor Jefe

      Gracias a ti por leernos XD

  • Alexrs95

    Muy buen tutorial, en cuanto pueda me pondré a probarla. Una duda ¿A partir de qué versión de Android podemos usar esta librería? Gracias :)

    • http://hackedbrain.blogspot.com/ JMPergar | Editor Jefe

      A partir de 1.6 si no recuerdo mal

  • javi

    Genial articulo, buscaba algo asi, y la verdad es que de este modo es facilisimo

    Muchas gracias y seguir asi.

  • Jorge Gomes

    MUy buen articulo, solo una cosilla, con esto es posible hacer tambien lo del header de las columans/paginas, me explico en el android market por cada pagina arriiba pone un texto(destacado,top free etc..) o mas simple aun poner puntos po cada pagina y resaltar el actual.

    gracias

  • Jorge Gomes
    • http://hackedbrain.blogspot.com/ JMPergar | Editor Jefe

      Si, yo tambien habia estado ojeandolo pero creo que la API nativa permite algo tambien, no te preocupes uno de nuestros redactores tiene en cola preparar un tutorial al respecto.

      • Jorge Gomes

        Perfecto pues, deseando ver ese tutorial.
        gracias

  • Nuria

    Hola

    Gracias por este magnífico tutorial.
    Mi pregunta es que una vez funcionando, si quiero poner un botón en la columna 2, lo pongo en el Layout de esta pero no acierto a como implementar el Listener desde la actividad.
    Podrían ayudarme?

    Muy agradecida

    Un saludo.

    • http://hackedbrain.blogspot.com/ JMPergar | Editor Jefe

      No lo he probado aun pero supongo que justo despues de inflar el layout en la clase recuperas el boton y le asocias el listener.

  • Pingback: ViewPager: Añadiendo títulos | Androcode()

  • Manuel Hernandez Lemus

    Hola que tal, buen día, primero muy buen sitio para aprender Android.

    Probé tu ejemplo y la verdad me gustaría crear una app con el estilo (Android Market, ahora GooglePlay), pero tengo una duda, el PageViewer solo se usa en el manejo de layouts?, es decir, si yo quisiera llamar un Activity dentro del PageViewer tendría que usar FragmentAdapter y a su vez FragmentActivity

    • http://hackedbrain.blogspot.com/ JMPergar | Editor Jefe

      No tengo la seguridad al 100% pero diria que si, que solo es compatible con Layouts, pero la pregunta es, ¿por que necesitas usar activities?

    • http://androcode.es/2011/11/viewpager-implementando-columnas/ Fran

      Hola pues eso mismo quisiera yo saber porque quiero que represente una lista en cada una de las columnas y no se como hacerlo haber si nos pueden echar una mano por favor, un saludo.

      • http://hackedbrain.blogspot.com/ JMPergar | Editor Jefe

        No puedes hacerlo usando ListView? Lo que no podras es usar ListActivity

        • gus

          Hola buenas, muy buen tutorial al igual que el viewPager con titulos, muchisimas gracias por ellos.
          He hecho los dos, y he conseguido mi ViewPager con titulos, pero debido a mi poca experiencia con android, me pasa lo mismo que a Fran, me gustaría añadir o listView o un WebView en cada columna , pero no consigo que me los muestre…
          He añadido al layout xml el webview, y en el Activity he añadido en el oncreate despues del inflate el codigo para iniciar el webview, pero no lo muestra, tampoco me da errores, alguna idea?? un poco de ayuda??
          Muchas gracias por vuestro trabajo

          • http://www.linkedin.com/in/jmpergar JMPergar | Editor Jefe

            No usado nunca un WebView dentro de un ViewPager, pero creo que para hacerlo hay que usar fragments, en concreto uno en especial que existe para ello.

          • Manuel Fabian

            Hola, ya me ha tocado implementar el viewpager con el viewPagerIndicator y me surgio el mismo problema, lo que ise es que
            el codigo del webView se agrega dentro del instantiateItem heredado de ViewPager, si pudieras poner un poco de codigo seria mas facil ayudarte

  • Victor

    Muy buen trabajo, y muchas gracias me sirvió mucho tu aportación.

  • Luis

    hola
    segui el tutorial y todo funciona con las columnas q queria mostrar pero tengo una duda, hay como incluir un ViewPager pero q no ocupe toda la pantalla.

    gracias

    • http://www.linkedin.com/in/jmpergar JMPergar | Editor Jefe

      Es trivial, igual que con cualquier otra vista, create tu propio layout y coloca el ViewPager como mas te convenga.

  • Igor

    Buenas, soy novato y no consigo que eche a rodar el ejemplo en Eclipse. Si hay algún alma caritativa que me pase el código completo de las actividades y de los layouts lo agradecería para que lo pueda aprender bien. Les dejo mi dirección de correo igorsinmas@gmail.com

  • yonaides

    esto era lo que estaba buscando! muchas gracias!

  • Pablo

    ¿Cómo me descargo el ejemplo? En Google Code no me aparece nada y copiando el código no me funciona. Gracias

    • http://www.linkedin.com/in/jmpergar JMPergar

      Deberás sincronizar el proyecto de Google Code vía SVN, no obstante si te vas a la sección de source (donde también obtendrás la url del repositorio a sincronizar) podrás navegar a través de las carpetas del proyecto y ojear toda la implementación del ejemplo.

  • JQ

    Amigo Muchas gracias.

    Al copiar y pegar jejeje Eclipse me dice:

    R.layout.columna1
    R.layout.columna2
    R.layout.columna3

    No sabe que son. “cannot be resolved or is not a field.

    Que estoy haciendo mal? Perdón si es algo tonto. Soy novato en el tema.

    Gracias

    • http://www.linkedin.com/in/jmpergar JMPergar

      Son los layouts que representaran cada una de tus columnas.

  • Juan Francisco Muñoz

    Muy buenas, antes de nada felicitarte por el magnifico trabajo. Tengo una duda respecto a esto, ¿hay alguna manera de “asignar” a cada columna una clogica de negocio diferente, es decir, que cada layout mostrado por la aplicacion tenga su .java (o .class) asociado.

    Para dejarlo mas claro quiero “hacer” una aplicación que inserte datos en una BBDD y que tenga varias ventanas, las cuales puedan ser vistas usando esta técnica en vez de usar las típicas pestañas.

    Mil gracias.

    • Juan Francisco Muñoz

      Volviendo a leer el articulo he visto el ejemplo de lo que quiero hacer claro, quiero hacer lo que hace el play store, que cada vista que muestre tenga su funcionalidad, pero no tengo claro donde establezco eso, ¿tengo que crear un intent? ¿si es así como y donde?

      Puntualizar que estoy empezando con esto de Android y por eso puede que no digas las cosas tal y como son XD

      Muchas gracias de nuevo.

      • http://www.linkedin.com/in/jmpergar JMPergar

        Usando fragments puedes hacerlo.