Create swipe views with tabs using ViewPager2

Swipe views allow you to navigate between sibling screens, such as tabs, with a horizontal finger gesture, or swipe. This navigation pattern is also referred to as horizontal paging. This topic teaches you 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 ViewPager2 widget. To use ViewPager2 and tabs, you need to add a dependency on ViewPager2 and on Material Components to your project.

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

<androidx.viewpager2.widget.ViewPager2
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, you need to hook this layout to a FragmentStateAdapter. Here's how you might use it to swipe across a collection of Fragment objects:

Kotlin

classCollectionDemoFragment:Fragment(){
// When requested, this adapter returns a DemoObjectFragment,
// representing an object in the collection.
privatelateinitvardemoCollectionAdapter:DemoCollectionAdapter
privatelateinitvarviewPager:ViewPager2
overridefunonCreateView(
inflater:LayoutInflater,
container:ViewGroup?,
savedInstanceState:Bundle?
):View? {
returninflater.inflate(R.layout.collection_demo,container,false)
}
overridefunonViewCreated(view:View,savedInstanceState:Bundle?){
demoCollectionAdapter=DemoCollectionAdapter(this)
viewPager=view.findViewById(R.id.pager)
viewPager.adapter=demoCollectionAdapter
}
}
classDemoCollectionAdapter(fragment:Fragment):FragmentStateAdapter(fragment){
overridefungetItemCount():Int=100
overridefuncreateFragment(position:Int):Fragment{
// Return a NEW fragment instance in createFragment(int)
valfragment=DemoObjectFragment()
fragment.arguments=Bundle().apply{
// Our object is just an integer :-P
putInt(ARG_OBJECT,position+1)
}
returnfragment
}
}
privateconstvalARG_OBJECT="object"
// Instances of this class are fragments representing a single
// object in our 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.
DemoCollectionAdapterdemoCollectionAdapter;
ViewPager2viewPager;
@Nullable
@Override
publicViewonCreateView(@NonNullLayoutInflaterinflater,@NullableViewGroupcontainer,
@NullableBundlesavedInstanceState){
returninflater.inflate(R.layout.collection_demo,container,false);
}
@Override
publicvoidonViewCreated(@NonNullViewview,@NullableBundlesavedInstanceState){
demoCollectionAdapter=newDemoCollectionAdapter(this);
viewPager=view.findViewById(R.id.pager);
viewPager.setAdapter(demoCollectionAdapter);
}
}
publicclass DemoCollectionAdapterextendsFragmentStateAdapter{
publicDemoCollectionAdapter(Fragmentfragment){
super(fragment);
}
@NonNull
@Override
publicFragmentcreateFragment(intposition){
// Return a NEW fragment instance in createFragment(int)
Fragmentfragment=newDemoObjectFragment();
Bundleargs=newBundle();
// Our object is just an integer :-P
args.putInt(DemoObjectFragment.ARG_OBJECT,position+1);
fragment.setArguments(args);
returnfragment;
}
@Override
publicintgetItemCount(){
return100;
}
}
// Instances of this class are fragments representing a single
// object in our collection.
publicclass DemoObjectFragmentextendsFragment{
publicstaticfinalStringARG_OBJECT="object";
@Nullable
@Override
publicViewonCreateView(@NonNullLayoutInflaterinflater,@NullableViewGroupcontainer,
@NullableBundlesavedInstanceState){
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 sections show how you can add tabs to help facilitate navigation between pages.

Add Tabs Using a TabLayout

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

Figure 1: A TabLayout with four tabs.

To include a TabLayout in a ViewPager2, add a <TabLayout> element above the <ViewPager2> element, as shown below:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>

Next, create a TabLayoutMediator to link the TabLayout to the ViewPager2, and attach it as follows:

Kotlin

classCollectionDemoFragment:Fragment(){
...
overridefunonViewCreated(view:View,savedInstanceState:Bundle?){
valtabLayout=view.findViewById(R.id.tab_layout)
TabLayoutMediator(tabLayout,viewPager){tab,position->
tab.text="OBJECT ${(position+1)}"
}.attach()
}
...
}

Java

publicclass CollectionDemoFragmentextendsFragment{
...
@Override
publicvoidonViewCreated(@NonNullViewview,@NullableBundlesavedInstanceState){
TabLayouttabLayout=view.findViewById(R.id.tab_layout);
newTabLayoutMediator(tabLayout,viewPager,
(tab,position)->tab.setText("OBJECT "+(position+1))
).attach();
}
...
}

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

Additional resources

To learn more about ViewPager2, see the following additional resources.

Samples

Videos

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.