Android ViewPager - Afficher l'aperçu de la page à gauche et à droite

107

J'utilise Android ViewPager. Ce que je veux faire, c'est afficher un aperçu de la page à gauche et à droite. J'ai vu où je peux utiliser un négatif pageMarginpour afficher un aperçu du côté droit.

setPageMargin(-100);

Est-il possible d'afficher un aperçu du côté gauche également? C'est fondamentalement quelque chose de similaire au widget de galerie que je recherche.

Brian Boyle
la source
Bonne question! J'ai récemment vérifié la source et je pense qu'il n'y a pas de meilleur moyen si vous ne voulez pas modifier le code src. Cela setPageMargin(-100)fonctionne- t-il correctement?
Macarse
le GalleryView fera mieux le travail, sauf si vous utilisez le ViewPger avec des fragments.
Ali AlNoaimi
J'ai pu le faire en utilisant la vue Galerie. identique à viewpager en aucune façon. Je ne sais pas pourquoi la galerie est obsolète
WillingLearner
Cette question a depuis été largement couverte dans le [post ici] [1] [1]: stackoverflow.com/questions/13914609/…
Ben Pearson
J'utilise Vierpager avec des fragments, puis-je utiliser la même approche?
asliyanage

Réponses:

206

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

  1. viewpager.setClipToPadding(false);
  2. viewpager.setPadding(left,0,right,0);

Si vous avez besoin d'espace entre deux pages dans le visualiseur, ajoutez

viewpager.setPageMargin(int);
Jiju Induchoodan
la source
2
Oui, je suis d'accord avec vous Jiju Induchoodan .. Pour plus d'informations, veuillez consulter blog.neteril.org/blog/2013/10/14/… et stackoverflow.com/questions/13914609/…
Sripathi
Cool, c'est si simple :) Est-il possible de redimensionner les aperçus sur les tailles droite et gauche sur les pages de changement de page de vue? Par exemple - si le fragment n'est pas au point - son échelle sera d'environ 0,8, mais lorsque nous le faisons glisser vers le centre - l'échelle augmentera à 1, et le fragment précédent de la vue centrale changera l'échelle à 0,8 en sortant de l'écran?
iamthevoid
Cela fonctionne! Mais lorsque j'essaye de zoomer sur la mise en page centrale, c'est le zoom vers le haut et le bas. La gauche et la droite ne sont pas visibles en raison du rembourrage. Veuillez consulter la question stackoverflow.com/questions/52710076/…
Anooj Krishnan G
ne fonctionne pas avec viewpager 2
hamiid reza Gholami
73

La réponse de @JijuInduchoodan est parfaite et fonctionne. Cependant, comme je suis relativement nouveau sur Android, il m'a fallu un certain temps pour le comprendre et le configurer correctement. Donc, je publie cette réponse pour référence future et aide toute autre personne qui est dans les mêmes chaussures que moi.

if (viewPager == null) 
        {

            // Initializing view pager
            viewPager = (ViewPager) findViewById(R.id.vpLookBook);

            // Disable clip to padding
            viewPager.setClipToPadding(false);
            // set padding manually, the more you set the padding the more you see of prev & next page
            viewPager.setPadding(40, 0, 40, 0);
            // sets a margin b/w individual pages to ensure that there is a gap b/w them
            viewPager.setPageMargin(20);
        }

Il n'est pas nécessaire de définir une largeur de ViewPager'spage dans l'adaptateur. Il n'y a pas de code supplémentaire requis pour voir la page précédente et suivante dans ViewPager. Toutefois, si vous souhaitez ajouter un espace vide en haut et en bas de chaque page, vous pouvez définir le code suivant sur ViewPager'sla mise en page parent de la page enfant.

android:paddingTop="20dp"
android:paddingBottom="20dp"

ViewPager final

Ce sera le look final du ViewPager.

Rohan Kandwal
la source
62

Solution avec le nouveau ViewPager2

De nos jours, vous devriez envisager d'utiliser ViewPager2 qui "remplace ViewPager, en résolvant la plupart des problèmes de son prédécesseur" :

  • Basé sur RecyclerView
  • Prise en charge de la mise en page RTL (de droite à gauche)
  • Support d'orientation verticale
  • Prise en charge fiable des fragments (y compris la gestion des modifications apportées à la collection Fragment sous-jacente)
  • Animations de changement de jeu de données (y compris la DiffUtilprise en charge)

Le résultat

entrez la description de l'image ici

Le code

Dans votre activité / fragment, configurez le ViewPager2:

// MyRecyclerViewAdapter is an standard RecyclerView.Adapter :)
viewPager2.adapter = MyRecyclerViewAdapter() 

// You need to retain one page on each side so that the next and previous items are visible
viewPager2.offscreenPageLimit = 1

// Add a PageTransformer that translates the next and previous items horizontally
// towards the center of the screen, which makes them visible
val nextItemVisiblePx = resources.getDimension(R.dimen.viewpager_next_item_visible)
val currentItemHorizontalMarginPx = resources.getDimension(R.dimen.viewpager_current_item_horizontal_margin)
val pageTranslationX = nextItemVisiblePx + currentItemHorizontalMarginPx
val pageTransformer = ViewPager2.PageTransformer { page: View, position: Float ->
    page.translationX = -pageTranslationX * position
    // Next line scales the item's height. You can remove it if you don't want this effect
    page.scaleY = 1 - (0.25f * abs(position))
    // If you want a fading effect uncomment the next line:
    // page.alpha = 0.25f + (1 - abs(position))
}
viewPager2.setPageTransformer(pageTransformer)

// The ItemDecoration gives the current (centered) item horizontal margin so that
// it doesn't occupy the whole screen width. Without it the items overlap
val itemDecoration = HorizontalMarginItemDecoration(
    context,
    R.dimen.viewpager_current_item_horizontal_margin
)
viewPager2.addItemDecoration(itemDecoration)

Ajoutez le HorizontalMarginItemDecoration, qui est trivial ItemDecoration:

/**
 * Adds margin to the left and right sides of the RecyclerView item.
 * Adapted from https://stackoverflow.com/a/27664023/4034572
 * @param horizontalMarginInDp the margin resource, in dp.
 */
class HorizontalMarginItemDecoration(context: Context, @DimenRes horizontalMarginInDp: Int) :
    RecyclerView.ItemDecoration() {

    private val horizontalMarginInPx: Int =
        context.resources.getDimension(horizontalMarginInDp).toInt()

    override fun getItemOffsets(
        outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
    ) {
        outRect.right = horizontalMarginInPx
        outRect.left = horizontalMarginInPx
    }

}

Ajoutez les dimensions qui contrôlent la quantité de l'élément précédent / suivant visible et la marge horizontale de l'élément actuel:

<dimen name="viewpager_next_item_visible">26dp</dimen>
<dimen name="viewpager_current_item_horizontal_margin">42dp</dimen>

entrez la description de l'image ici

Enfin, ajoutez le ViewPager2à votre mise en page:

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

Une chose importante: un ViewPager2élément doit avoir layout_height="match_parent"(sinon il lève une IllegalStateException), vous devriez donc faire quelque chose comme:

<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" <-- this!
    app:cardCornerRadius="8dp"
    app:cardUseCompatPadding="true">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="280dp">

        <!-- ... -->

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>

Exemples de PageTransformer

Google a ajouté un guide sur ViewPager2 qui a 2 PageTransformerimplémentations que vous pouvez utiliser comme source d'inspiration: https://developer.android.com/training/animation/screen-slide-2

À propos du nouveau ViewPager2

Albert Vila Calvo
la source
Même problème sur les appareils oreo, le début et la fin du rembourrage fonctionnent comme prévu sur d'autres appareils mais oreo après ViewPager2. PageTransformer a résolu le problème, les rembourrages sont toujours les mêmes et j'ai dû ajouterviewpager.setPageTransformer { page, position -> page.translationX = -1 * position }
zgr
Je dois déplacer légèrement la page du pager de vue pour obtenir cet effet
Muhammad Saqib
peu importe, j'ai oublié d'ajouter cette ligne setOffscreenPageLimit(1):)
Muhammad Saqib
C'est la meilleure solution que j'aie jamais trouvée. Cela fonctionne parfaitement mais oui N'OUBLIEZ PAS de définir la largeur, la hauteur de l'élément de ViewPager2 sur MATCH_PARENT.
khushbu
26

En 2017, un tel comportement peut également être facilement obtenu en utilisant RecyclerViewavec PagerSnapHelper (ajouté dans la version 25.1.0 de la bibliothèque de support v7):

entrez la description de l'image ici

Il y a quelque temps, j'avais besoin d'une telle fonctionnalité de type viewpager et j'ai préparé une petite bibliothèque:

MetalRecyclerPagerView - vous pouvez trouver tout le code ainsi que des exemples.

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

J'espère que cela aide quelqu'un et gagnera quelques heures :)

Alexander Bilchuk
la source
Hors sujet, car parfois seul un téléavertisseur est nécessaire mais bon à savoir! Merci d'avoir partagé!
sud007
C'est génial. J'avais déjà des tonnes de code d'aide RecyclerView. Il suffit d'ajouter un simple new PagerSnapHelper().attachToRecyclerView(recyclerView)et j'ai la capture de page.
Steve
9

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

44kksharma
la source
7

Vous pouvez le faire dans un fichier xml, utilisez simplement le code ci-dessous:

 android:clipToPadding="false"
 android:paddingLeft="XX"
 android:paddingRight="XX"

Par exemple:

<androidx.viewpager.widget.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:paddingLeft="30dp"
        android:paddingRight="30dp" />

Remarque: si vous avez besoin d'espace entre les pages, définissez le remplissage / la marge sur les fragments enfants

sma6871
la source
3
J'ai voté contre. Désolé frère. Cela a fonctionné cette fois !! A voté à nouveau
shikhar bansal
1

Pour ceux qui ont du mal à avoir cela sur différents écrans,

mPager.setClipToPadding(false);
DisplayMetrics displayMetrics = new DisplayMetrics();
self.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
int paddingToSet = width/4; //set this ratio according to how much of the next and previos screen you want to show.
mPager.setPadding(paddingToSet,0,paddingToSet,0);
Saurabh Verma
la source
0

Notez que lorsque vous définissez des paddings sans zéro sur un viewpager, le placement edgeeffect du viewpager est foiré, c'est un bogue du viewpager, voir ici: viewpager edgeeffect bug

Vous pouvez soit désactiver l'effet de bord en définissant android:overScrollMode="never"sur le visualiseur, soit corriger le bogue avec une version légèrement modifiée de la classe EdgeEffect : ViewPagerEdgeEffect fix

ssynhtn
la source
-10

Utilisez cet adaptateur de fragment et cette classe pour afficher le visionneur dans le défilement gauche et droit, ajoutez les classes nécessaires pour faire défiler les pages suivantes.

package com.rmn.viewpager;

import java.util.List;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

/**
 * The <code>PagerAdapter</code> serves the fragments when paging.
 * @author mwho
 */
public class PagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;
    /**
     * @param fm
     * @param fragments
     */
    public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }
    /* (non-Javadoc)
     * @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
     */
    @Override
    public Fragment getItem(int position) {
        return this.fragments.get(position);
    }

    /* (non-Javadoc)
     * @see android.support.v4.view.PagerAdapter#getCount()
     */
    @Override
    public int getCount() {
        return this.fragments.size();
    }
}



package com.manishkpr.viewpager;


import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

public class ViewPagerAdapter extends FragmentPagerAdapter {
    private Context _context;

    public ViewPagerAdapter(Context context, FragmentManager fm) {
        super(fm);  
        _context=context;

        }
    @Override
    public Fragment getItem(int position) {
        Fragment f = new Fragment();
        switch(position){
        case 0:
            f=LayoutOne.newInstance(_context);  
            break;
        case 1:
            f=LayoutTwo.newInstance(_context);  
            break;
        }
        return f;
    }
    @Override
    public int getCount() {
        return 2;
    }

}
Veerababu Medisetti
la source