Android
ViewPager
Recherche…
Introduction
ViewPager est un gestionnaire de mise en page qui permet à l'utilisateur de parcourir les pages de données à gauche et à droite. Il est le plus souvent utilisé conjointement avec Fragment, qui est un moyen pratique de fournir et de gérer le cycle de vie de chaque page.
Remarques
Une chose importante à noter à propos de l'utilisation de ViewPager est qu'il existe deux versions différentes de FragmentPagerAdapter
et de FragmentStatePagerAdapter
.
Si vous utilisez des fragments natifs android.app.Fragment
avec un FragmentPagerAdapter ou un FragmentStatePagerAdapter, vous devez utiliser les versions de la bibliothèque de support v13 de l'adaptateur, à savoir android.support.v13.app.FragmentStatePagerAdapter
.
Si vous utilisez la bibliothèque de support android.support.v4.app.Fragment
avec un fragment FragmentPagerAdapter ou FragmentStatePagerAdapter, vous devez utiliser les versions de bibliothèque de support v4 de l'adaptateur, à savoir android.support.v4.app.FragmentStatePagerAdapter
.
Utilisation de base de ViewPager avec des fragments
Un ViewPager
permet d'afficher plusieurs fragments dans une activité qui peut être parcourue en basculant à gauche ou à droite. Un ViewPager
doit être alimenté par Views ou Fragments à l'aide d'un PagerAdapter
.
Il existe cependant deux implémentations plus spécifiques que vous trouverez plus utiles dans le cas de l'utilisation de Fragments, à savoir FragmentPagerAdapter
et FragmentStatePagerAdapter
. Lorsqu'un fragment doit être instancié pour la première fois, getItem(position)
sera appelé pour chaque position nécessitant une instanciation. La méthode getCount()
renvoie le nombre total de pages afin que ViewPager
sache combien de fragments doivent être affichés.
FragmentPagerAdapter
et FragmentStatePagerAdapter
conservent tous deux un cache des fragments que ViewPager
devra afficher. Par défaut, ViewPager
essaiera de stocker un maximum de 3 fragments correspondant au fragment actuellement visible, et ceux situés à droite et à gauche. Aussi FragmentStatePagerAdapter
gardera l'état de chacun de vos fragments.
Sachez que les deux implémentations supposent que vos fragments conserveront leurs positions, donc si vous conservez une liste des fragments au lieu d'en avoir un nombre statique comme vous pouvez le voir dans la méthode getItem()
, vous devrez créer une sous-classe de PagerAdapter
et remplacer au moins instantiateItem()
, destroyItem()
et getItemPosition()
méthodes.
Ajoutez simplement un ViewPager dans votre mise en page comme décrit dans l' exemple de base :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<android.support.v4.view.ViewPager
android:id="@+id/vpPager">
</android.support.v4.view.ViewPager>
</LinearLayout>
Définissez ensuite l'adaptateur qui déterminera le nombre de pages existantes et le fragment à afficher pour chaque page de l'adaptateur.
public class MyViewPagerActivity extends AppCompatActivity {
private static final String TAG = MyViewPagerActivity.class.getName();
private MyPagerAdapter mFragmentAdapter;
private ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myActivityLayout);
//Apply the Adapter
mFragmentAdapter = new MyPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(mFragmentAdapter);
}
private class MyPagerAdapter extends FragmentPagerAdapter{
public MyPagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
// Returns the fragment to display for that page
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
default:
return null;
}
}
// Returns total number of pages
@Override
public int getCount() {
return 3;
}
}
}
Si vous utilisez android.app.Fragment
vous devez ajouter cette dépendance:
compile 'com.android.support:support-v13:25.3.1'
Si vous utilisez android.support.v4.app.Fragment
vous devez ajouter cette dépendance:
compile 'com.android.support:support-fragment:25.3.1'
ViewPager avec TabLayout
Un TabLayout
peut être utilisé pour faciliter la navigation.
Vous pouvez définir les onglets pour chaque fragment de votre adaptateur à l'aide de la méthode TabLayout.newTab()
, mais il existe une autre méthode plus pratique et plus simple pour cette tâche: TabLayout.setupWithViewPager()
.
Cette méthode se synchronise en créant et en supprimant des onglets en fonction du contenu de l'adaptateur associé à votre ViewPager
chaque fois que vous l'appelez.
En outre, il va définir un rappel chaque fois que l'utilisateur retourne la page, l'onglet correspondant sera sélectionné.
Il suffit de définir une mise en page
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
app:tabMode="scrollable" />
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" />
</LinearLayout>
Ensuite, implémentez FragmentPagerAdapter
et appliquez-le à ViewPager
:
public class MyViewPagerActivity extends AppCompatActivity {
private static final String TAG = MyViewPagerActivity.class.getName();
private MyPagerAdapter mFragmentAdapter;
private ViewPager mViewPager;
private TabLayout mTabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myActivityLayout);
// Get the ViewPager and apply the PagerAdapter
mFragmentAdapter = new MyPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(mFragmentAdapter);
// link the tabLayout and the viewpager together
mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
mTabLayout.setupWithViewPager(mViewPager);
}
private class MyPagerAdapter extends FragmentPagerAdapter{
public MyPagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
// Returns the fragment to display for that page
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
default:
return null;
}
}
// Will be displayed as the tab's label
@Override
public CharSequence getPageTitle(int position) {
switch(position) {
case 0:
return "Fragment 1 title";
case 1:
return "Fragment 2 title";
case 2:
return "Fragment 3 title";
default:
return null;
}
}
// Returns total number of pages
@Override
public int getCount() {
return 3;
}
}
}
ViewPager avec PreférenceFragment
Jusqu'à récemment, l'utilisation de android.support.v4.app.FragmentPagerAdapter
empêchait l'utilisation de PreferenceFragment
comme l'un des fragments utilisés dans FragmentPagerAdapter.
Les dernières versions de la bibliothèque de support v7 incluent désormais la classe PreferenceFragmentCompat
, qui fonctionnera avec un ViewPager et la version v4 de FragmentPagerAdapter.
Exemple de fragment qui étend PreferenceFragmentCompat
:
import android.os.Bundle;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.view.View;
public class MySettingsPrefFragment extends PreferenceFragmentCompat {
public MySettingsPrefFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.fragment_settings_pref);
}
@Override
public void onCreatePreferences(Bundle bundle, String s) {
}
}
Vous pouvez maintenant utiliser ce fragment dans une sous-classe android.support.v4.app.FragmentPagerAdapter
:
private class PagerAdapterWithSettings extends FragmentPagerAdapter {
public PagerAdapterWithSettings(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new FragmentOne();
case 1:
return new FragmentTwo();
case 2:
return new MySettingsPrefFragment();
default:
return null;
}
}
// .......
}
Ajouter un ViewPager
Assurez-vous que la dépendance suivante est ajoutée au fichier build.gradle
votre application sous les dépendances:
compile 'com.android.support:support-core-ui:25.3.0'
Ajoutez ensuite le ViewPager
à votre disposition d'activité:
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Définissez ensuite votre PagerAdapter
:
public class MyPagerAdapter extends PagerAdapter {
private Context mContext;
public CustomPagerAdapter(Context context) {
mContext = context;
}
@Override
public Object instantiateItem(ViewGroup collection, int position) {
// Create the page for the given position. For example:
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.xxxx, collection, false);
collection.addView(layout);
return layout;
}
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
// Remove a page for the given position. For example:
collection.removeView((View) view);
}
@Override
public int getCount() {
//Return the number of views available.
return numberOfPages;
}
@Override
public boolean isViewFromObject(View view, Object object) {
// Determines whether a page View is associated with a specific key object
// as returned by instantiateItem(ViewGroup, int). For example:
return view == object;
}
}
Enfin, configurez le ViewPager
dans votre activité:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new MyPagerAdapter(this));
}
}
ViewPager avec un indicateur de points
Tout ce dont nous avons besoin sont: ViewPager , TabLayout et 2 tirables pour les points sélectionnés et par défaut.
Tout d'abord, nous devons ajouter TabLayout
à notre disposition d'écran et le connecter à ViewPager
. Nous pouvons le faire de deux manières:
Onglet imbriquéMise en forme dans ViewPager
<android.support.v4.view.ViewPager
android:id="@+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.view.ViewPager>
Dans ce cas,
TabLayout
sera automatiquement connecté àViewPager
, maisTabLayout
sera à côté deViewPager
, pas sur lui.
TabLayout séparé
<android.support.v4.view.ViewPager
android:id="@+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Dans ce cas, nous pouvons mettre
TabLayout
n'importe où, mais nous devons connecterTabLayout
avecViewPager
programmation
ViewPager pager = (ViewPager) view.findViewById(R.id.photos_viewpager);
PagerAdapter adapter = new PhotosAdapter(getChildFragmentManager(), photosUrl);
pager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(pager, true);
Une fois que nous avons créé notre mise en page, nous devons préparer nos points. Nous créons donc trois fichiers: selected_dot.xml
, default_dot.xml
et tab_selector.xml
.
selected_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="@color/colorAccent"/>
</shape>
</item>
</layer-list>
default_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="@android:color/darker_gray"/>
</shape>
</item>
</layer-list>
tab_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/selected_dot"
android:state_selected="true"/>
<item android:drawable="@drawable/default_dot"/>
</selector>
Maintenant, nous devons ajouter seulement 3 lignes de code à TabLayout
dans notre présentation XML et vous avez terminé.
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
Configuration de OnPageChangeListener
Si vous devez écouter les modifications apportées à la page sélectionnée, vous pouvez implémenter l'écouteur ViewPager.OnPageChangeListener
sur ViewPager:
viewPager.addOnPageChangeListener(new OnPageChangeListener() {
// This method will be invoked when a new page becomes selected. Animation is not necessarily complete.
@Override
public void onPageSelected(int position) {
// Your code
}
// This method will be invoked when the current page is scrolled, either as part of
// a programmatically initiated smooth scroll or a user initiated touch scroll.
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Your code
}
// Called when the scroll state changes. Useful for discovering when the user begins
// dragging, when the pager is automatically settling to the current page,
// or when it is fully stopped/idle.
@Override
public void onPageScrollStateChanged(int state) {
// Your code
}
});