ViewPager avec les limites de page précédentes et suivantes

Je conçois une vue avec plusieurs pages. Je veux que les bords des pages précédentes et suivantes apparaissent comme ci-dessous et implémentent un balayage à 2 doigts pour passer d’une page à l’autre.

entrer la description de l'image ici

J’ai essayé d’utiliser ViewPager avec une marge de page négative comme suggéré ici, mais cela ne montre qu’un des bords de l’écran, pas les deux simultanément.

Sinon, y a-t-il un moyen de positionner une partie de ma vue en dehors de l’écran et ensuite de l’animer en lui donnant un effet de type ViewPager .

Comment dois-je m’y prendre? Merci !

    Me citant d’ un article de blog sur ce sujet :

    La troisième approche vient de Dave Smith, co-auteur du livre bien connu Android Recipes. Il est allé dans une direction très différente, en utilisant un conteneur personnalisé que les enfants handicapés clippant pour afficher plus d’une page à la fois.

    Son exemple de code publié montre le tout en action. Son conteneur ( com.example.pagercontainer.PagerContainer ) enveloppe le ViewPager et appelle setClipChildren(false); sur lui-même, même si le ViewPager est focalisé sur une page sélectionnée, les autres pages qui ont des coordonnées au-delà des limites de ViewPager sont toujours visibles, tant qu’elles tiennent dans le PagerContainer . En dimensionnant le ViewPager pour qu’il soit plus petit que le PagerContainer , le ViewPager peut dimensionner ses pages à cette taille, laissant la place aux autres pages. PagerContainer , cependant, doit aider un peu avec les événements tactiles, car ViewPager ne ViewPager que les événements de balayage sur ses propres limites visibles, en ignorant les pages visibles sur les côtés.

    entrer la description de l'image ici

    J’ai une solution similaire:

    Sur le viewpager, placez le padding gauche et droit, par exemple 20dp. Définissez également la marge de la page sur le visualiseur, par exemple la moitié du remplissage du pagineur. Et n’oubliez pas de désactiver le remplissage des clips.

     tilePager.setPadding(defaultGap, 0, defaultGap, 0); tilePager.setClipToPadding(false); tilePager.setPageMargin(halfGap); 
    1. Définissez le remplissage gauche et droit pour la vue entière de l’article. Exemple xml (page_item.xml):

           
    2. Ensuite, définissez une marge de page négative pour PageView égale à 2 * (remplissage de la vue précédente)

       int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2, getResources().getDisplayMesortingcs()); mViewPager.setPageMargin(-margin); 
    3. Optionnel. Définissez un remplissage à gauche pour le premier élément et zéro pour le dernier élément pour masquer les bords vides. Vous pouvez le faire dans la PageAdapter ou Page fragment.

    Pour afficher un aperçu des pages gauche et droite, définissez les deux valeurs suivantes

     viewpager.setClipToPadding(false) viewpager.setPadding(left,0,right,0) 

    Si vous avez besoin d’espace entre deux pages dans le viewpager, ajoutez viewpager.setPageMargin (int)

    Android ViewPager – Afficher l’aperçu de la page à gauche et à droite

    si quelqu’un cherchait encore une solution, j’avais personnalisé le ViewPage pour y parvenir sans utiliser de marge négative, trouvez un exemple de projet ici https://github.com/44kksharma/Android-ViewPager-Carousel-UI il devrait fonctionner dans la plupart des cas mais vous peut toujours définir la marge de la page avec mPager.setPageMargin(margin in pixel);

    Téléchargez le code source ici ( ViewPager avec les limites de page précédentes et suivantes )

    MainActivity.java

     package com.deepshikha.viewpager; import android.content.Context; import android.content.res.Configuration; import android.os.Build; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.DisplayMesortingcs; import android.util.Log; import android.util.SparseArray; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; public class MainActivity extends FragmentActivity { ViewPager pager; MyPageAdapter obj_adapter; Ssortingng str_device; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { pager = (ViewPager) findViewById(R.id.viewpager); differentDensityAndScreenSize(getApplicationContext()); List fragments = getFragments(); pager.setAdapter(obj_adapter); pager.setClipToPadding(false); if (str_device.equals("normal-hdpi")){ pager.setPadding(160, 0, 160, 0); }else if (str_device.equals("normal-mdpi")){ pager.setPadding(160, 0, 160, 0); }else if (str_device.equals("normal-xhdpi")){ pager.setPadding(160, 0, 160, 0); }else if (str_device.equals("normal-xxhdpi")){ pager.setPadding(180, 0, 180, 0); }else if (str_device.equals("normal-xxxhdpi")){ pager.setPadding(180, 0, 180, 0); }else if (str_device.equals("normal-unknown")){ pager.setPadding(160, 0, 160, 0); }else { } obj_adapter = new MyPageAdapter(getSupportFragmentManager(), fragments); pager.setPageTransformer(true, new ExpandingViewPagerTransformer()); pager.setAdapter(obj_adapter); } class MyPageAdapter extends FragmentPagerAdapter { private List fragments; public MyPageAdapter(FragmentManager fm, List fragments) { super(fm); this.fragments = fragments; } @Override public Fragment getItem(int position) { return this.fragments.get(position); } @Override public int getCount() { return this.fragments.size(); } } private List getFragments() { List fList = new ArrayList(); fList.add(MyFragment.newInstance("Fragment 1",R.drawable.imags)); fList.add(MyFragment.newInstance("Fragment 2",R.drawable.image1)); fList.add(MyFragment.newInstance("Fragment 3",R.drawable.image2)); fList.add(MyFragment.newInstance("Fragment 4",R.drawable.image3)); fList.add(MyFragment.newInstance("Fragment 5",R.drawable.image4)); return fList; } public int differentDensityAndScreenSize(Context context) { int value = 20; Ssortingng str = ""; if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) { switch (context.getResources().getDisplayMesortingcs().densityDpi) { case DisplayMesortingcs.DENSITY_LOW: str = "small-ldpi"; // Log.e("small 1","small-ldpi"); value = 20; break; case DisplayMesortingcs.DENSITY_MEDIUM: str = "small-mdpi"; // Log.e("small 1","small-mdpi"); value = 20; break; case DisplayMesortingcs.DENSITY_HIGH: str = "small-hdpi"; // Log.e("small 1","small-hdpi"); value = 20; break; case DisplayMesortingcs.DENSITY_XHIGH: str = "small-xhdpi"; // Log.e("small 1","small-xhdpi"); value = 20; break; case DisplayMesortingcs.DENSITY_XXHIGH: str = "small-xxhdpi"; // Log.e("small 1","small-xxhdpi"); value = 20; break; case DisplayMesortingcs.DENSITY_XXXHIGH: str = "small-xxxhdpi"; //Log.e("small 1","small-xxxhdpi"); value = 20; break; case DisplayMesortingcs.DENSITY_TV: str = "small-tvdpi"; // Log.e("small 1","small-tvdpi"); value = 20; break; default: str = "small-unknown"; value = 20; break; } } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) { switch (context.getResources().getDisplayMesortingcs().densityDpi) { case DisplayMesortingcs.DENSITY_LOW: str = "normal-ldpi"; // Log.e("normal-ldpi 1","normal-ldpi"); str_device = "normal-ldpi"; value = 82; break; case DisplayMesortingcs.DENSITY_MEDIUM: // Log.e("normal-mdpi 1","normal-mdpi"); str = "normal-mdpi"; value = 82; str_device = "normal-mdpi"; break; case DisplayMesortingcs.DENSITY_HIGH: // Log.e("normal-hdpi 1","normal-hdpi"); str = "normal-hdpi"; str_device = "normal-hdpi"; value = 82; break; case DisplayMesortingcs.DENSITY_XHIGH: //Log.e("normal-xhdpi 1","normal-xhdpi"); str = "normal-xhdpi"; str_device = "normal-xhdpi"; value = 90; break; case DisplayMesortingcs.DENSITY_XXHIGH: // Log.e("normal-xxhdpi 1","normal-xxhdpi"); str = "normal-xxhdpi"; str_device = "normal-xxhdpi"; value = 96; break; case DisplayMesortingcs.DENSITY_XXXHIGH: //Log.e("normal-xxxhdpi","normal-xxxhdpi"); str = "normal-xxxhdpi"; str_device = "normal-xxxhdpi"; value = 96; break; case DisplayMesortingcs.DENSITY_TV: //Log.e("DENSITY_TV 1","normal-mdpi"); str = "normal-tvdpi"; str_device = "normal-tvmdpi"; value = 96; break; default: // Log.e("normal-unknown","normal-unknown"); str = "normal-unknown"; str_device = "normal-unknown"; value = 82; break; } } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) { switch (context.getResources().getDisplayMesortingcs().densityDpi) { case DisplayMesortingcs.DENSITY_LOW: str = "large-ldpi"; // Log.e("large-ldpi 1","normal-ldpi"); value = 78; break; case DisplayMesortingcs.DENSITY_MEDIUM: str = "large-mdpi"; //Log.e("large-ldpi 1","normal-mdpi"); value = 78; break; case DisplayMesortingcs.DENSITY_HIGH: //Log.e("large-ldpi 1","normal-hdpi"); str = "large-hdpi"; value = 78; break; case DisplayMesortingcs.DENSITY_XHIGH: // Log.e("large-ldpi 1","normal-xhdpi"); str = "large-xhdpi"; value = 125; break; case DisplayMesortingcs.DENSITY_XXHIGH: //Log.e("large-ldpi 1","normal-xxhdpi"); str = "large-xxhdpi"; value = 125; break; case DisplayMesortingcs.DENSITY_XXXHIGH: // Log.e("large-ldpi 1","normal-xxxhdpi"); str = "large-xxxhdpi"; value = 125; break; case DisplayMesortingcs.DENSITY_TV: //Log.e("large-ldpi 1","normal-tvdpi"); str = "large-tvdpi"; value = 125; break; default: str = "large-unknown"; value = 78; break; } } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) { switch (context.getResources().getDisplayMesortingcs().densityDpi) { case DisplayMesortingcs.DENSITY_LOW: // Log.e("large-ldpi 1","normal-ldpi"); str = "xlarge-ldpi"; value = 125; break; case DisplayMesortingcs.DENSITY_MEDIUM: // Log.e("large-ldpi 1","normal-mdpi"); str = "xlarge-mdpi"; value = 125; break; case DisplayMesortingcs.DENSITY_HIGH: //Log.e("large-ldpi 1","normal-hdpi"); str = "xlarge-hdpi"; value = 125; break; case DisplayMesortingcs.DENSITY_XHIGH: // Log.e("large-ldpi 1","normal-hdpi"); str = "xlarge-xhdpi"; value = 125; break; case DisplayMesortingcs.DENSITY_XXHIGH: // Log.e("large-ldpi 1","normal-xxhdpi"); str = "xlarge-xxhdpi"; value = 125; break; case DisplayMesortingcs.DENSITY_XXXHIGH: // Log.e("large-ldpi 1","normal-xxxhdpi"); str = "xlarge-xxxhdpi"; value = 125; break; case DisplayMesortingcs.DENSITY_TV: //Log.e("large-ldpi 1","normal-tvdpi"); str = "xlarge-tvdpi"; value = 125; break; default: str = "xlarge-unknown"; value = 125; break; } } return value; } } 

    Il y a quelque temps, j’avais besoin d’une telle fonctionnalité et j’ai préparé une petite bibliothèque qui utilise RecyclerView avec PagerSnapHelper (ajouté dans la version 25.1.0 de la bibliothèque de support v7) au lieu du classique ViewPager :

    MetalRecyclerPagerView – vous pouvez trouver tout le code avec des exemples ici.

    Il se compose principalement d’un fichier de classe unique: MetalRecyclerViewPager.java (et deux fichiers XML: attrs.xml et ids.xml ).

    J’espère que ça aide quelqu’un 🙂