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 del ViewPager
en Android.
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:
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:
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.
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter