Create swipe views with tabs using ViewPager
Stay organized with collections Save and categorize content based on your preferences.

Swipe views let you navigate between sibling screens, such as tabs, with a horizontal finger gesture (swipe). This navigation pattern is also referred to as horizontal paging. This document shows how to create a tab layout with swipe views for switching between tabs, along with how to show a title strip instead of tabs.

Implement swipe views

You can create swipe views using AndroidX's ViewPager widget. To use ViewPager and tabs, add dependencies on Viewpager and on Material Components in your project.

To set up your layout with ViewPager, add the <ViewPager> element to your XML layout. For example, if each page in the swipe view needs to consume the entire layout, then your layout looks like this:

<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

To insert child views that represent each page, hook this layout to a PagerAdapter. You can choose between two kinds of built-in adapters:

  • FragmentPagerAdapter: use this when navigating between a small, fixed number of sibling screens.
  • FragmentStatePagerAdapter: use this when paging across an unknown number of pages. FragmentStatePagerAdapter optimizes memory usage by destroying fragments as the user navigates away.

Here's an example of how you can use FragmentStatePagerAdapter to swipe across a collection of Fragment objects:

Kotlin

classCollectionDemoFragment:Fragment(){
// When requested, this adapter returns a DemoObjectFragment, representing
// an object in the collection.
privatelateinitvardemoCollectionPagerAdapter:DemoCollectionPagerAdapter
privatelateinitvarviewPager:ViewPager
overridefunonCreateView(inflater:LayoutInflater,
container:ViewGroup?,
savedInstanceState:Bundle?):View? {
returninflater.inflate(R.layout.collection_demo,container,false)
}
overridefunonViewCreated(view:View,savedInstanceState:Bundle?){
demoCollectionPagerAdapter=DemoCollectionPagerAdapter(childFragmentManager)
viewPager=view.findViewById(R.id.pager)
viewPager.adapter=demoCollectionPagerAdapter
}
}
// Since this is an object collection, use a FragmentStatePagerAdapter, not a
// FragmentPagerAdapter.
classDemoCollectionPagerAdapter(fm:FragmentManager):FragmentStatePagerAdapter(fm){
overridefungetCount():Int=100
overridefungetItem(i:Int):Fragment{
valfragment=DemoObjectFragment()
fragment.arguments=Bundle().apply{
// Our object is just an integer :-P
putInt(ARG_OBJECT,i+1)
}
returnfragment
}
overridefungetPageTitle(position:Int):CharSequence{
return"OBJECT ${(position+1)}"
}
}
privateconstvalARG_OBJECT="object"
// Instances of this class are fragments representing a single object in your
// collection.
classDemoObjectFragment:Fragment(){
overridefunonCreateView(inflater:LayoutInflater,
container:ViewGroup?,
savedInstanceState:Bundle?):View{
returninflater.inflate(R.layout.fragment_collection_object,container,false)
}
overridefunonViewCreated(view:View,savedInstanceState:Bundle?){
arguments?.takeIf{it.containsKey(ARG_OBJECT)}?.apply{
valtextView:TextView=view.findViewById(android.R.id.text1)
textView.text=getInt(ARG_OBJECT).toString()
}
}
}

Java

publicclass CollectionDemoFragmentextendsFragment{
// When requested, this adapter returns a DemoObjectFragment, representing
// an object in the collection.
DemoCollectionPagerAdapterdemoCollectionPagerAdapter;
ViewPagerviewPager;
@Nullable
@Override
publicViewonCreateView(@NonNullLayoutInflaterinflater,
@NullableViewGroupcontainer,
@NullableBundlesavedInstanceState){
returninflater.inflate(R.layout.collection_demo,container,false);
}
@Override
publicvoidonViewCreated(@NonNullViewview,@NullableBundlesavedInstanceState){
demoCollectionPagerAdapter=newDemoCollectionPagerAdapter(getChildFragmentManager());
viewPager=view.findViewById(R.id.pager);
viewPager.setAdapter(demoCollectionPagerAdapter);
}
}
// Since this is an object collection, use a FragmentStatePagerAdapter, not a
// FragmentPagerAdapter.
publicclass DemoCollectionPagerAdapterextendsFragmentStatePagerAdapter{
publicDemoCollectionPagerAdapter(FragmentManagerfm){
super(fm);
}
@Override
publicFragmentgetItem(inti){
Fragmentfragment=newDemoObjectFragment();
Bundleargs=newBundle();
// Our object is just an integer.
args.putInt(DemoObjectFragment.ARG_OBJECT,i+1);
fragment.setArguments(args);
returnfragment;
}
@Override
publicintgetCount(){
return100;
}
@Override
publicCharSequencegetPageTitle(intposition){
return"OBJECT "+(position+1);
}
}
// Instances of this class are fragments representing a single object in your
// collection.
publicclass DemoObjectFragmentextendsFragment{
publicstaticfinalStringARG_OBJECT="object";
@Override
publicViewonCreateView(LayoutInflaterinflater,
ViewGroupcontainer,BundlesavedInstanceState){
returninflater.inflate(R.layout.fragment_collection_object,container,false);
}
@Override
publicvoidonViewCreated(@NonNullViewview,@NullableBundlesavedInstanceState){
Bundleargs=getArguments();
((TextView)view.findViewById(android.R.id.text1))
.setText(Integer.toString(args.getInt(ARG_OBJECT)));
}
}

The following section shows how to add tabs to facilitate navigation between pages.

Add tabs using a TabLayout

A TabLayout provides a way to display tabs horizontally. When used with a ViewPager, a TabLayout provides a familiar interface for navigating between pages in a swipe view.

Figure 1. A TabLayout with four tabs.

To include a TabLayout in a ViewPager, add a <TabLayout> element inside the <ViewPager> element, as shown in the following example:

<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.viewpager.widget.ViewPager>

Use setupWithViewPager() to link the TabLayout to the ViewPager, as shown in the following example. The individual tabs in the TabLayout are automatically populated with the page titles from the PagerAdapter.

Kotlin

classCollectionDemoFragment:Fragment(){
...
overridefunonViewCreated(view:View,savedInstanceState:Bundle?){
valtabLayout=view.findViewById(R.id.tab_layout)
tabLayout.setupWithViewPager(viewPager)
}
...
}
classDemoCollectionPagerAdapter(fm:FragmentManager):FragmentStatePagerAdapter(fm){
overridefungetCount():Int=4
overridefungetPageTitle(position:Int):CharSequence{
return"OBJECT ${(position+1)}"
}
...
}

Java

publicclass CollectionDemoFragmentextendsFragment{
...
@Override
publicvoidonViewCreated(@NonNullViewview,@NullableBundlesavedInstanceState){
TabLayouttabLayout=view.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager);
}
...
}
publicclass DemoCollectionPagerAdapterextendsFragmentStatePagerAdapter{
...
@Override
publicintgetCount(){
return4;
}
@Override
publicCharSequencegetPageTitle(intposition){
return"OBJECT "+(position+1);
}
...
}

For additional design guidance for tab layouts, see the Material Design documentation for tabs.

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2025年02月10日 UTC.