Menú Navegación Páginas

El blog de Antonio Leiva sobre diseño y desarrollo de interfaces en Android

ViewPagerIndicator y ViewPager para crear pestañas en Android

ViewPagerIndicator y ViewPager para crear pestañas en Android
  • Twitter
  • Facebook
  • Google Plus
  • LinkedIn

Es un hecho que las pestañas como tal están desapareciendo poco a poco de las aplicaciones Android. El motivo es que es mucho más cómodo arrastrar con un dedo la pantalla para pasar a la siguiente que hacer click en la parte superior sobre una superficie mucho menor.

La tendencia actual es usar estas vistas que pueden ser arrastradas e informar al usuario de en cuál está en la parte superior, al estilo de lo que podemos ver en el Google Play o incluso en la parte de artistas de la nueva aplicación de Spotify para Android de la que hablábamos el otro día.

ViewPagerIndicator en Spotify

Esta funcionalidad no viene por defecto en ninguno de los APIs actuales, y tenemos que recurrir, como siempre, al Support Package de Android y a una librería externa: ViewPageIndicator.

ViewPagerIndicator

Si quieres utilizar ViewPagerIndicator con ActionBarSherlock, puedes ver este artículo donde integro las dos librerías.

Para poder utilizar la librería, seguimos paso similares a los que vimos con el ActionBarCompat:

  1. Descargamos la librería de la página de ViewPageIndicator
  2. Creamos un nuevo proyecto y le indicamos que genere desde una fuente existente. Seleccionamos la ruta.
  3. Vamos a nuestro proyecto, y con el botón derecho accedemos a Properties, Android y en la sección Library pulsamos “Add…” y la añadimos.

Si por ejemplo queremos añadir un Indicator de tipo Title, en nuestra actividad principal añadimos el siguiente XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

  	<com.viewpagerindicator.TitlePageIndicator
        android:id="@+id/indicator"
        android:padding="10dip"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
    />

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
    />
</LinearLayout>

Esto nos incluye un ViewPager, que es el que permite la posibilidad de incluir varias vistas en una misma actividad y pasar de una a otra arrastrando. La funcionalidad se incluye en versiones nuevas de Android, pero usamos el Support Package para tenerlo disponible en versiones previas. El TitlePageIndicator nos mostrará una cabecera de título que indica en qué vista estamos.

Creamos un FragmentAdapter que extienda FragmentPagerAdapter y que implemente TitleProvider. Rellenamos los métodos que obligatorios, ocupándonos de devolver el Fragment correspondiente en el método getItem en función de la posición, y lo mismo para getTitle:

public class FragmentAdapter extends FragmentPagerAdapter {

	private String[] titles = { "Title1", "Title2", "Title3" };

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

	public CharSequence getPageTitle(int position) {

		return titles[position];
	}

	@Override
	public Fragment getItem(int position) {

		return new MyFragment();
	}

	@Override
	public int getCount() {

		return titles.length;
	}

}

Finalmente añadimos los siguiente atributos a nuestra actividad principal:

	private FragmentAdapter mAdapter;
	private ViewPager mPager;
	private PageIndicator mIndicator;

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

		mAdapter = new FragmentAdapter(getSupportFragmentManager());

		mPager = (ViewPager)findViewById(R.id.pager);
		mPager.setAdapter(mAdapter);

		mIndicator = (TitlePageIndicator)findViewById(R.id.indicator);
		mIndicator.setViewPager(mPager);
	}

Este es un ejemplo muy simple, pero tenéis muchos más en el paquete de descarga.

Descarga | ViewPagerIndicator

Actualización 29/08/2012: gracias a los comentarios de Alberto Hernández he actualizado  el código a la última versión de la librería, que ha cambiado su implementación para reutilizar algunas funcionalidades del API de Android.

¿Te ha gustado? Compártelo

39 Comentarios

  1. Hola! en primer lugar enhorabuena por tu blog ^^
    He llegado aquí porque estaba intentando poner unas pestañas con TabActivity pero está obsoleto como tu bien indicas.
    He pegado el código que has puesto tú pero no tengo muy claro donde va la clase FragmentAdapter, ¿creas otro fichero .java o va dentro del principal?
    Estoy aprendiendo y aún me lía un poco la estructura de ficheros.

    Gracias y un saludo.

    • Hola Marta, muchas gracias!
      Efectivamente, FragmentAdapter es una nueva clase en un nuevo archivo java.
      La segunda parte va en el onCreate de la actividad principal, o en la que quieras tener tus pestañas.

      Si necesitas más ayuda no dudes en preguntar, o enviarme un correo desde el área de contacto.

  2. Hola de nuevo! me preguntaba si tenías alguna idea de como conectar la aplicación de Android a un MS SQL server y que muestre datos de la base de datos conectada a él.

    • Pues por lo que tengo entendido no hay librerías para eso. No te queda más remedio que crearte web services en el servidor que te devuelvan las información que quieres, lo más cómodo probablemente será en formato JSON.

  3. Ok gracias lo investigaré porque yo de servidores y eso no tengo ni idea pero como estoy haciendo las prácticas para una empresa me habían comentado si podía intentarlo.

  4. hola, estuve tratando de utilizar el codigo que has puesto y Eclipse me dice que tengo un error cuando hago el 
     implements TitleProvider. Y las opciones que me ofrece son create interface TitleProvider o Change to ´TestSuitProvider´. Creo que se debe a un problema con la libreria de 
    ViewPageIndicator, pero no estoy seguro. Desde ya muchas gracias y buen aporte

    • Hola! Efectivamente, esa clase es de la librería de ViewPagerIndicator. Sospecho que es que no está bien incluida la librería en el proyecto. ¿Todo lo demás compila sin problema? Comprueba en las opciones del proyecto de com_viewpagerindicator que tienes marcado el campo IsLibrary. Te adjunto una captura. En principio viene marcado, pero por si acaso. Y luego revisa los pasos de añadirlo a tu proyecto como librería.

      • bueno, muchas gracias por la respuesta. Ahora me pongo manos a la obra, luego comento como me fue

      • dos preguntas mas, eh seguido las instrucciones del link de la 
         ActionBarCompat para usar el proyecto como libreria. 1) cuando elijo abrir proyecto nuevo desde uno existente, que carpeta elijo la que dice sample o la que dice lib.  2) una vez hechos los pasos para usar el proyecto como libreria, es necesario importar el packt? 

        • Elige la carpeta lib, la sample es un ejemplo donde se usa la librería. Para importarlo, te vas a tu proyecto, botón derecho y Properties. En la pestaña Android, en la parte de abajo hay una parte que pone library, pulsa en Add y eliges el proyecto de la anterior.

          • Gracias, al fin logre importar la libreria, importaba el contenido de la carpeta sample. Lo he hecho importando la carpeta Lib y funcionó perfectamente, ya lo habia hecho, pero no entiendo porque no habia funcionado anterior mente.
            Ahora el único lugar que dice que tengo error es en la lineamAdapter = new FragmentAdapter(getSupportFragmentManager()); de mi actividad principalDiciendome que getSupportFragmentManager() is undefined for the type MainActivityMi MainActivity extiende a ActivityY la sugerencia es que cree el metodo

          • Ese método corresponde a la Support Library, que tendrás que usarla si quieres que funcionen en móviles anteriores a las 3.0. Si no, sólo para no liarte de momento puedes sustituirlo por getFragmentManager(), y luego revísate este tema: http://goo.gl/ldEDC. Para incluirla en tu proyecto sólo tienes que darle al botón derecho sobre el proyecto, Android Tools, Add Support Library… Suerte!

          • hola, no es problema de la Support Library porque ya la tenia agragada, ya que los ViewPager son parte de la libreria y no tengo errores con eso, solo con este metodo. Voy a seguir buscando a ver si encuentro el problema. Gracias de todas formas por tu respuestas

          • bien, al fin pude hacer que reconozca el método, mi mainactivity extendia de Activity, lo cambie por FragmentActivity. Lo había hecho con anterioridad pero salían mas errores, eh probado cerrar eclipse y volver a extender de FragmentActivity y funciono. Muchas gracias por tu ayuda Antonio, y a Alberto tambien por algunos aportes.

    • Cristianego, me acabo de percatar de que he contestado a tu pregunta sin querer, échale un vistazo a mi comentario porque han cambiado la interfaz de ViewPageIndicator y ya no se usa el TitleProvider.

      • muchas gracias Alberto, no la había visto porque no se me actualizo el navegador. Gracias nuevamente. Ahora me pongo a ver eso, disculpen si mis preguntas son muy obvias para otros, pero es que estoy aprendiendo de apoco y hasta ahora nunca hice un proyecto que tenga que usar como libreria otro xD. Saludos

  5. Muchas gracias, la documentación de la biblioteca no es gran cosa y este post me ha ayudado. 

    Quería comentar que han cambiado algunas cosas en la última versión, concretamente ya no hay que extender de TitleProvider porque directamente usa el método getPageTitle que ya viene en el support package. 

    Por si quieres actualizar el post, habría que quitar el “implements TitleProvider” y actualizar la cabecera del método getTitle a:

    @Override public CharSequence getPageTitle(int position){ return titles[position]; }

    • Gracias! Lo actualizaré. Y también voy a echarle un vistazo a tu Cuatro en raya HD, que tiene muy buena pinta. Un saludo.

      • Jeje, gracias, tengo la web “oficial” un poco descuidada. Espero que te guste, los desafíos son totalmente originales y hasta donde yo sé es el único cuatro en raya que los incorpora. Lo del viewpager es precisamente para organizar mejor los desafíos de éste y otros juegos que estoy preparando.

        • Pues ya he modificado la entrada con tus comentarios. Muchas gracias de nuevo. Suena interesante, a ver si tengo un rato y la pruebo. Además he leído que se pueden jugar partidas online, puede estar bien. Saludos!

  6. Pues parece que la biblioteca funciona muy bien, lo he probado ya en el emulador con Froyo, en un Desire con ICS y en un Galaxy Nexus con Jelly Bean. Pero vamos, después de ver las apps que la usan no tenía duda de su estabilidad.

    Por cierto, en cada fragmento he metido una lista con scroll, en alguna ocasión parece que compiten los gestos de desplazamiento horizontal del ViewPager con los verticales de la ListView y no se aclara qué quiero hacer.

    • Yo también lo he usado con una ListView y no me ha dado demasiada sensación de confusión el tema de los gestos. Así de primeras no se me ocurre nada que puedas ponerle para que priorice una sobre otra, quizá jugando un poco con los MotionEvent, pero no sé si habrá solución por ese camino.

  7. Alguien tendrá este ejemplo??? me causa error en esta parte mAdapter = new FragmentAdapter(getSupportFragmentManager()); y en este metodo lo cambie por Fragment en vez de MyFragment @Override

    public Fragment getItem(int position) {

    return new MyFragment();
    }

    • Esta tarde lo busco a ver si lo puedo colgar. Con esa información no sabría decirte qué ocurre.

      • Gracias, el error me lo marca en getSupportFragmentManager()

        • Asegúrate de que están bien añadidas las referencias. La actividad principal tiene que extender de FragmentActivity del Support Package en lugar de extender de Activity.

        • Tambien me da error en el getSupportFragmentManager()… como lo solucionaste?

          Las importaciones estan ok

  8. Listo viejo, ya logré cuadrar la importación. jeje que enrredo tan impresionante.

    Ahora en el codigo del FragmentAdapter.java me sale error en:

    return new MyFragment();

    MyFragment cannot be resolved to a type

    Gracias por la ayuda

  9. Hola, primero enhorabuena por el blog, es realmente útil.

    Quería comentar varias cosas:

    – Para poder compilar bien el proyecto he tenido que cambiar la definición de la variable mIndicator de la siguiente manera: private TitlePageIndicator mIndicator;

    – En el caso que tengas 3 pestañas cada una de ellas con un fragment, ¿cómo puedo conseguir que por defecto al cargar la activity muestre la segunda de ellas? Por más que lo intento siempre muestra la primera.

    Gracias y saludos!!!

    • mIndicator.setCurrentItem(1);

      Eso te selecciona la segunda pestaña, pero tienes que usarlo antes de que se haya pintado la interfaz (en el onCreate por ejemplo). Una vez pintado, ya no tiene efecto.

  10. Gracias, muy útil

  11. Se puede hacer que llame a otra actividad distinta por cada desplazamiento ?

    • Un ViewPager suele contener fragments, y como mucho se puede hacer uno con vistas, pero no le encuentro sentido a lo quita dices de cambiar de Activity

  12. me sale errror acá:
    private FragmentAdapter mAdapter;
    private ViewPager mPager;
    private PageIndicator mIndicator;

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

    mAdapter = new FragmentAdapter(getSupportFragmentManager());

    mPager = (ViewPager)findViewById(R.id.pager);
    mPager.setAdapter(mAdapter);

    mIndicator = (TitlePageIndicator)findViewById(R.id.indicator);
    mIndicator.setViewPager(mPager);
    }

  13. muy bueno el aporte, muy completo.

  14. Hola Como puedo hacer para que mi app empiece en la 2 pestaña o en la 3 o en la del medio por favor

    • Sería `viewPager.setCurrentItem(position);
      Te recomiendo en cualquier caso que le eches un vistazo a TabLayout de la Design Support Library. Este artículo es bastante antiguo y hay alternativas mejores hoy en día.

Trackbacks/Pingbacks

  1. 5 consejos para convertir tu aplicación iOS a Android | LiME - [...] importante posicionarlas en la parte superior. Además la tendencia actual, como ya explicaba en el tutorial sobre pestañas en …
  2. Android Fragments con pestañas | LiME Creative Labs - [...] recomiendo la opción de los paneles desplazables de los que ya hablamos aquí, mediante ViewPager y ViewPagerIndicator. Pero sí …
  3. Añadir un background a una Activity en Android | LiME Creative Labs | LiME Creative Labs - [...] el siguiente artículo, te explico como utilizar ViewPagerIndicator, una de las librerías gratuitas más famosas de Android. [...]
  4. ActionBarSherlock y ViewPagerIndicator: la pareja perfecta - [...] y ViewPagerIndicator no sólo funcionan bien en conjunto, sino que son prácticamente imprescindibles para casi cualquier [...]

Deja tus comentarios