Créer des vues à balayer avec des onglets à l'aide de ViewPager2

Les vues à balayer vous permettent de naviguer entre des écrans frères tels que des onglets d'un geste horizontal du doigt ou balayage. Ce schéma de navigation est également appelé pagination horizontale. Cette rubrique vous explique comment créer une mise en page d'onglets avec des vues à balayer pour passer d'un onglet à l'autre, et comment afficher une barre de titre plutôt que des onglets.

Implémenter des vues à balayer

Vous pouvez créer des vues à balayer à l'aide du widget ViewPager2 d'AndroidX. Pour utiliser ViewPager2 et les onglets, vous devez ajouter une dépendance à ViewPager2 et aux composants matériels de votre projet.

Pour configurer votre mise en page avec ViewPager2, ajoutez l'élément <ViewPager2> à votre mise en page XML. Par exemple, si chaque page de la vue à balayer doit utiliser l'intégralité de la mise en page, elle doit se présenter comme suit :

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

Pour insérer des vues enfants représentant chaque page, vous devez associer cette mise en page à un FragmentStateAdapter. Voici comment l'utiliser pour balayer un ensemble d'objets Fragment :

class CollectionDemoFragment : Fragment() {
   
// When requested, this adapter returns a DemoObjectFragment,
   
// representing an object in the collection.
   
private lateinit var demoCollectionAdapter: DemoCollectionAdapter
   
private lateinit var viewPager: ViewPager2

   
override fun onCreateView(
        inflater
: LayoutInflater,
        container
: ViewGroup?,
        savedInstanceState
: Bundle?
   
): View? {
       
return inflater.inflate(R.layout.collection_demo, container, false)
   
}

   
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        demoCollectionAdapter
= DemoCollectionAdapter(this)
        viewPager
= view.findViewById(R.id.pager)
        viewPager
.adapter = demoCollectionAdapter
   
}
}

class DemoCollectionAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {

   
override fun getItemCount(): Int = 100

   
override fun createFragment(position: Int): Fragment {
       
// Return a NEW fragment instance in createFragment(int)
       
val fragment = DemoObjectFragment()
        fragment
.arguments = Bundle().apply {
           
// Our object is just an integer :-P
            putInt
(ARG_OBJECT, position + 1)
       
}
       
return fragment
   
}
}

private const val ARG_OBJECT = "object"

// Instances of this class are fragments representing a single
// object in our collection.
class DemoObjectFragment : Fragment() {

   
override fun onCreateView(
        inflater
: LayoutInflater,
        container
: ViewGroup?,
        savedInstanceState
: Bundle?
   
): View {
       
return inflater.inflate(R.layout.fragment_collection_object, container, false)
   
}

   
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        arguments
?.takeIf { it.containsKey(ARG_OBJECT) }?.apply {
           
val textView: TextView = view.findViewById(android.R.id.text1)
            textView
.text = getInt(ARG_OBJECT).toString()
       
}
   
}
}
public class CollectionDemoFragment extends Fragment {
   
// When requested, this adapter returns a DemoObjectFragment,
   
// representing an object in the collection.
   
DemoCollectionAdapter demoCollectionAdapter;
   
ViewPager2 viewPager;

   
@Nullable
   
@Override
   
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
           
@Nullable Bundle savedInstanceState) {
       
return inflater.inflate(R.layout.collection_demo, container, false);
   
}

   
@Override
   
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        demoCollectionAdapter
= new DemoCollectionAdapter(this);
        viewPager
= view.findViewById(R.id.pager);
        viewPager
.setAdapter(demoCollectionAdapter);
   
}
}

public class DemoCollectionAdapter extends FragmentStateAdapter {
   
public DemoCollectionAdapter(Fragment fragment) {
       
super(fragment);
   
}

   
@NonNull
   
@Override
   
public Fragment createFragment(int position) {
       
// Return a NEW fragment instance in createFragment(int)
       
Fragment fragment = new DemoObjectFragment();
       
Bundle args = new Bundle();
       
// Our object is just an integer :-P
        args
.putInt(DemoObjectFragment.ARG_OBJECT, position + 1);
        fragment
.setArguments(args);
       
return fragment;
   
}

   
@Override
   
public int getItemCount() {
       
return 100;
   
}
}

// Instances of this class are fragments representing a single
// object in our collection.
public class DemoObjectFragment extends Fragment {
   
public static final String ARG_OBJECT = "object";

   
@Nullable
   
@Override
   
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
           
@Nullable Bundle savedInstanceState) {
       
return inflater.inflate(R.layout.fragment_collection_object, container, false);
   
}

   
@Override
   
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
       
Bundle args = getArguments();
       
((TextView) view.findViewById(android.R.id.text1))
               
.setText(Integer.toString(args.getInt(ARG_OBJECT)));
   
}
}

Les sections suivantes expliquent comment ajouter des onglets pour faciliter la navigation entre les pages.

Ajouter des onglets avec TabLayout

Un TabLayout permet d'afficher les onglets horizontalement. Lorsqu'il est utilisé avec un ViewPager2, un TabLayout peut fournir une interface familière permettant de naviguer entre les pages en mode balayage.

Figure 1 : TabLayout avec quatre onglets

Pour inclure un TabLayout dans un ViewPager2, ajoutez un élément <TabLayout> au-dessus de l'élément <ViewPager2>, comme indiqué ci-dessous :

<LinearLayout xmlns: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>

Ensuite, créez un TabLayoutMediator pour associer le TabLayout au ViewPager2, puis associez-le comme suit :

class CollectionDemoFragment : Fragment() {
   
...
   
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
       
val tabLayout = view.findViewById(R.id.tab_layout)
       
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            tab
.text = "OBJECT ${(position + 1)}"
       
}.attach()
   
}
   
...
}
public class CollectionDemoFragment extends Fragment {
   
...
   
@Override
   
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
       
TabLayout tabLayout = view.findViewById(R.id.tab_layout);
       
new TabLayoutMediator(tabLayout, viewPager,
               
(tab, position) -> tab.setText("OBJECT " + (position + 1))
       
).attach();
   
}
   
...
}

Pour obtenir des conseils supplémentaires sur la mise en page des onglets, consultez les documents Material Design pour les onglets.

Ressources supplémentaires

Pour en savoir plus sur ViewPager2, consultez les ressources supplémentaires suivantes.

Exemples

Vidéos