Los ViewPager para desplazarse entre pantallas (fragments) en Android

08-11-2016 - Andrés Cruz

Los ViewPager para desplazarse entre pantallas (fragments) en Android
In english

Este material forma parte de mi curso y libro completo; puedes adquirirlos desde el apartado de libros y/o cursos.

En esta entrada veremos cómo emplear los ViewPager los cuales permiten manejar convenientemente el caracteristico movimiento lateral (derecha/izquierda) o swipe de forma nativa sin nececidad de emplear código extra.

Los ViewPager son empleados frecuentemente en conjunto con los fragments.

Hace unas entradas anteriores vimos cómo Cómo establecer fragments en los tags en Android con los TabHost y hoy veremos un ejercicio similar pero con una tecnología más actualizada, la cual vendría siendo en un futuro el reemplazo de estos.

Los viewPager son unos tipos de vistas que cada vez son más comunes como en aplicaciones como la Google Play y permite desplazarnos entre distintas pantallas a través de un menú lateral:

Uso de viewPager en Legado Gourmet

Uso del ViewPager en Android.

Uso de viewPager en Google Play

Uso del ViewPager en Android.

Como puedes ver, puedes ubicarla donde quieras, arriba o abajo como cualquier otra vista en Android.

Un punto fuerte de los ViewPager es que permiten emplear de manera nativa el swipe que es el característico movimiento lateral para desplazarnos entre pantallas:

swipe  en Gmail

A la práctica:

Desde nuestro Android Studio creamos un layout como el siguiente:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/rlContainer"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
   tools:context=".MainActivity">   <include
       android:id="@+id/appbar"
       layout="@layout/toolbar" />   <FrameLayout
       android:id="@+id/frameLayout"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:paddingTop="50dp">       <android.support.v4.view.ViewPager
           android:id="@+id/viewpager"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />
   </FrameLayout>   <android.support.design.widget.TabLayout
       android:id="@+id/appbartabs"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize"
       android:layout_alignBottom="@+id/frameLayout"
       android:layout_alignParentBottom="true"
       app:tabGravity="fill"
       app:tabIndicatorColor="@color/colorAccent"
       app:tabMode="fixed"/>
</RelativeLayout>

Como vemos no hay nada raro, un elemento raíz que en nuestro ejemplo es un RelativeLayout pero puede ser cualquier otro como un LinearLayout, un toolbar cuyo contenido lo pueden detallar en el código fuente que puedes obtener al comienzo y final de esta entrada y el TabLayout que instanciamos para definir nuestros tabs que permiten trasladarnos entre los fragments que componentes el ViewPager (además del swipe).

Desde nuestra actividad instanciamos los objetos pertinentes :

Toolbar toolbar = (Toolbar) findViewById(R.id.appbar);
viewPager = (ViewPager) findViewById(R.id.viewpager);

Y el TabLayout:

final TabLayout tabLayout = (TabLayout) findViewById(R.id.appbartabs);

Ahora debemos definir un adapter que nos ayudará a construir nuestro tabs y desplazarnos entre los fragments correspondientes:

public class MiFragmentPagerAdapter extends FragmentPagerAdapter {
   private ArrayList<String> tags;   public MiFragmentPagerAdapter(FragmentManager fm, ArrayListArrayList<String> tags, Activity activity) {
       super(fm);
       this.tags = tags;
   }   @Override
   public int getCount() {
       return tags.size();
   }   @Override
   public Fragment getItem(int position) {       Fragment f = NULL;       switch(position) {
           case 0:
               f = new Fragment1(); //1
               break;
           case 1:
               f = new Fragment2(); //2
               break;
           case 2:
               f = new Fragment1();//v1
               break;
       }       return f;
   }   @Override
   public CharSequence getPageTitle(int position) {
       return tags.get(position);
   }
}

Cómo ves, nada complicado; sobreescribimos la clase FragmentPagerAdapter junto con el método es el getItem(int position) en donde definimos los fragments a desplazarnos, como puedes ver son tres fragments definidos para 3 tabs.

El método CharSequence permite definir el título para nuestros tabs.

Volviendo a nuestra actividad, invocamos al adapter anteriormente definido:

viewPager.setAdapter(new MiFragmentPagerAdapter(
       getSupportFragmentManager(), tags, MainActivity.this));

Ahora establecemos iconos a nuestros tabs: con la siguiente función:

tabLayout.getTabAt(0).setIcon(ICONS[0]);
tabLayout.getTabAt(1).setIcon(ICONS[1]);
tabLayout.getTabAt(2).setIcon(ICONS[2]);

Esto último es opcional, si no defines iconos simplemente aparecerán los textos, pero es buena idea siempre especificar algunos iconos.

Con esto estamos listos y tenemos una aplicación como la siguiente:

viewPager ejemplo

Pero aún podemos sacar más partido de los ViewPager como veremos a continuación.

Establecer vistas personalizados

Puede ser que la vista predefinida de los tabs nos cause algunos inconvenientes, la separación del texto a los iconos, no querer incluir textos etc, si este es tu caso debes saber que podemos definir una vista personalizada para los ViewPager de la siguiente forma.

En este ejemplo definiremos una vista que conste de una imagen, es decir, sin los textos que llamaremos customtab.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical">   <ImageView
       android:id="@+id/ivIcon"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center_horizontal" />
</LinearLayout>

En nuestra actividad hacemos lo siguiente:

final int[] ICONS = new int[]{
       R.drawable.vino_off,
       R.drawable.cerveza_off,
       R.drawable.vinosint_off,
       R.drawable.gourmet_off
};...for (int i = 0; i < 3; i++) {
    ImageView imageView = new ImageView(ListadosActivity.this);    View view = getLayoutInflater().inflate(R.layout.customtab, NULL);
    ((ImageView)view.findViewById(R.id.ivIcon)).setImageResource(ICONS[i]);
    tabLayout.getTabAt(i).setCustomView(view);
}

Remover el swipe

Si por alguna razón te molesta el swipe, puedes quitarselo de encima definiendo nuestro propio ViewPager que llamaremos como no CustomViewPager:

public class CustomViewPager extends ViewPager {

   private boolean enabled;

   public CustomViewPager(Context context, AttributeSet attrs) {
       super(context, attrs);
       this.enabled = true;
   }   @Override
   public boolean onTouchEvent(MotionEvent event) {
       if (this.enabled) {
           return super.onTouchEvent(event);
       }       return false;
   }   @Override
   public boolean onInterceptTouchEvent(MotionEvent event) {
       if (this.enabled) {
           return super.onInterceptTouchEvent(event);
       }       return false;
   }   public void setPagingEnabled(boolean enabled) {
       this.enabled = enabled;
   }
}

Desde nuestra actividad no tenemos que hacer nada del otro mundo, solo colocar CustomViewPager en vez de ViewPager:

ViewPager viewPager = (CustomViewPager) findViewById(R.id.viewpager);

E invocar al método:

viewPager.setPagingEnabled(false);

Con esto podrás quitarte de encima el "terrible" efecto swipe.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.

!Cursos a!

10$

En Udemy

Quedan días!

Ver los cursos
¡Hazte afiliado en Gumroad!

!Cursos desde!

4$

En Academia

Ver los cursos

!Libros desde!

1$

Ver los libros
!Web Alojada en Hostinger!