How to Use ViewPager for Navigating between Fragments (With TabLayout)
Making Fragments Scroll Nicely
ViewPager is a layout manager that allows the user to scroll left and right to navigate through multiple Fragments with a sliding animation. An adapter handles all the transactions between different Fragments. This way, FragmentTransaction.replace()
does not have to be called every time the user scrolls. After the tutorial there will be a few tips to avoid common errors and enhance the user experience if your code does not work as expected. You can find the source code of this project here.
Step 1: Put a ViewPager widget in your xml layout. I put the widget in activity_main.xml
and assigned its id to be view_pager
.
Step 2: Set up the child Fragments you would like to display. I made 3 child Fragments, calling them ChildFragment1
, ChildFragment2
, and ChildFragment3
. Remember to have them extend support.v4.app.fragment
. Now make layouts for all three of the Fragments. I call them child_fragment_1_layout
, child_fragment_2_layout
, and child_fragment_3_layout
. For simplicity, I will put one Button
in each layout (with ids button_1
, button_2
, and button_3
respectively) and have them make a Toast
when they are clicked. Override the onCreateView()
method and inflate the layouts. Wire up the buttons to display a different Toast
.
Step 3: Make an adapter for the ViewPager. You will have to extend either theFragmentPagerAdapter
or the FragmentStatePagerAdapter
. For this tutorial we will use the FragmentPagerAdapter
. The difference between the two can be found here. After extending the FragmentPagerAdapter
, you will need to call super(FragmentManager)
in your constructor and implement the methods getItem(position)
and getCount()
. The getItem(position)
method is used to return the fragment at the corresponding position, ordered from left to right. So ChildFragment1
would be at position 0, ChildFragment2
would be at position 1, and ChildFragment3
would be at position 2. The getCount()
method is to count how many Fragments there are to display, and in this case, there are 3.
Step 4: Now find your ViewPager
in MainActivity
and call the setAdapter()
method and pass in your custom adapter. If you are doing this in another Fragment (Nested Fragments), you will have to pass in getChildFragmentManager()
in the argument of your adapter instead. Now your ViewPager
is all set!
Using ViewPager with TabLayout
Step 5: You can display tabs with ViewPager
really easily. (You can use ViewPagerTitleStrip
and ViewPagerTabStrip
as well.) Include a TabLayout
in your activity_main.xml
. I will give it an id tab_layout
. Remember to change the constraint of your ViewPager
so it does not block the TabLayout
.
Step 6: Go to MainActivity
and find the TabLayout
. Then call setupWithViewPager()
and pass in your ViewPager
as the argument.
Step 7: Finally, go to your adapter and change the title of each Fragment. Override the getPageTitle()
method.
The result should look like this:
Avoiding Errors and Enhancing the User Experience
Q: Why does an Exception occur when I tried to change something in the 3rd Fragment from the 1st Fragment?
A: By default, ViewPager
only loads its adjacent Fragments (one to the left and one to the right), and if you tried to change the unloaded Fragments there will be an error.
Q: While scrolling within the ViewPager
I noticed a small amount of input delay and sometimes the View
s suddenly pop into the page instead of sliding over. What can I do?
A: There are 2 reasons that this may occur. First you may be using too many Fragments in your FragmentPagerAdapter
. Consider using a FragmentStatePagerAdapter
instead. It is a better option if there is a large number of child Fragments. Second, you are probably loading too many views in your fragment. There are 3 ways to fix that problem. First you can load the content in the View
s after the ViewPager
is idle. You can listen for that change with the ViewPager.OnPageChangeListener
. Second, you can increase the default amount of pages loaded with the ViewPager.setOffScreenPageLimit()
method. Finally, you should always use a RecyclerView
instead of a ListView
in your child Fragments because it reuses cells as the user scrolls up and down.