The ViewPagers to move between screens (fragments) in Android

- Andrés Cruz

En español
The ViewPagers to move between screens (fragments) in Android

In this entry we will see how to use the ViewPagers which allow you to conveniently handle the characteristic lateral movement (right/left) or swipe natively without the need to use extra code.

ViewPagers are often used in conjunction with fragments.

A few previous posts ago we saw how to establish fragments in tags in Android with TabHosts and today we will see a similar exercise but with a more up-to-date technology, which would be their replacement in the future.

The viewPagers are types of views that are increasingly common in applications such as Google Play and allow us to move between different screens through a side menu:

Uso de viewPager en Legado Gourmet

Using the ViewPager in Android.

Uso de viewPager en Google Play

Using the ViewPager in Android.

As you can see, you can place it wherever you want, top or bottom like any other view in Android.

A strong point of the ViewPagers is that they allow you to use the swipe natively, which is the characteristic lateral movement to move between screens:

swipe  en Gmail

To practice:

From our Android Studio we create a layout like the following:

<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>

As we can see there is nothing unusual, a root element that in our example is a RelativeLayout but can be any other such as a LinearLayout, a toolbar whose content can be detailed in the source code that you can get at the beginning and end of this entry and the TabLayout that we instantiate to define our tabs that allow us to move between the fragments that make up the ViewPager (in addition to the swipe).

From our activity we instantiate the relevant objects:

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

And the TabLayout:

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

Now we need to define an adapter that will help us build our tabs and navigate between the corresponding fragments:

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);
   }
}

As you can see, nothing complicated; We overwrite the FragmentPagerAdapter class together with the method is the getItem(int position) where we define the fragments to scroll, as you can see there are three fragments defined for 3 tabs.

The CharSequence method allows us to define the title for our tabs.

Going back to our activity, we call the previously defined adapter:

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

Now we set icons to our tabs: with the following function:

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

The latter is optional, if you don't define icons, the texts will simply appear, but it is a good idea to always specify some icons.

With this we are ready and we have an application like the following:

viewPager ejemplo

But we can still get more out of ViewPagers as we will see below.

Set custom views

It may be that the predefined view of the tabs causes us some inconveniences, the separation of the text from the icons, not wanting to include texts, etc. If this is your case, you should know that we can define a custom view for the ViewPagers in the following way.

In this example we will define a view that consists of an image, that is, without the texts that we will call 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>

In our activity we do the following:

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);
}

Remove the swipe

If for some reason the swipe bothers you, you can get rid of it by defining our own ViewPager which we'll call 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;
   }
}

From our activity we don't have to do anything special, just place CustomViewPager instead of ViewPager:

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

And call the method:

viewPager.setPagingEnabled(false);

With this you can get rid of the "terrible" swipe effect.

Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.