46 votes

Le ViewPager peut-il avoir plusieurs vues par page ?

Après avoir essayé la galerie et la vue à défilement horizontal, j'ai constaté que la vue Pager répond à mes besoins, mais qu'il lui manque une petite chose. L'afficheur peut-il avoir plusieurs vues par page ?

Je sais que View Pager n'affiche qu'une seule vue/page par balayage. Je me demandais si je pouvais limiter la largeur de mes vues pour que la deuxième vue qui suit s'affiche ?

Par exemple : J'ai 3 vues et je veux que l'écran affiche la vue 1 et une partie de la vue 2 pour que l'utilisateur sache qu'il y a plus de contenu et qu'il puisse glisser vers la vue 2.

|view 1|view 2|view 3|
|screen   |

0 votes

Avez-vous essayé de faire une maquette pour voir si cela fonctionne ? Il me semble que cela ne prendrait pas beaucoup de temps de le coder et de l'essayer.

0 votes

Le téléaffichage lui-même limite chaque vue à l'ensemble de l'écran. La raison pour laquelle j'ai publié ce message est de savoir si quelqu'un a de l'expérience avec le View Pager et s'il est possible d'afficher plus de deux vues sur le même écran.

1 votes

Utiliser ce lien et remplacer la méthode onInterceptTouchEvent et y retourner faux .

61voto

Paul Lammertsma Points 12817

J'ai découvert qu'une solution peut-être encore plus simple consistait à spécifier une marge négative pour le ViewPager. J'ai créé le projet MultiViewPager sur GitHub, auquel vous pouvez jeter un coup d'œil :

https://github.com/Pixplicity/MultiViewPager

Bien que MultiViewPager attende une vue enfant pour spécifier la dimension, le principe tourne autour de la définition de la marge de la page :

ViewPager.setPageMargin(
    getResources().getDimensionPixelOffset(R.dimen.viewpager_margin));

J'ai ensuite spécifié cette dimension dans mon dimens.xml :

<dimen name="viewpager_margin">-64dp</dimen>

Pour compenser le chevauchement des pages, la vue du contenu de chaque page a la marge opposée :

android:layout_marginLeft="@dimen/viewpager_margin_fix"
android:layout_marginRight="@dimen/viewpager_margin_fix"

Encore une fois dans dimens.xml :

<dimen name="viewpager_margin_fix">32dp</dimen>

(Notez que le viewpager_margin_fix est la moitié de la dimension absolue viewpager_margin dimension.)

Nous avons mis en œuvre cette dans le journal néerlandais App De Telegraaf Krant :

Phone example in De Telegraaf KrantTablet example

1 votes

Je n'arrive pas à le faire fonctionner avec votre solution, pouvez-vous poster un exemple ? thx

0 votes

Je n'arrive pas non plus à le faire fonctionner. Plus précisément, alors que la marge du viewpager semble être définie, la compensation avec Android:layout_marginRight & Left dans mon FrameLayout ne semble rien faire. Tout ce que je vois, ce sont des pages qui se chevauchent... L'aperçu de la mise en page d'Android Studio montre que les marges auraient dû être appliquées. (notez que j'utilise Android-support-v4)

0 votes

En fonction de la manière dont vous avez composé la mise en page à l'intérieur de chaque page, il se peut que vous souhaitiez plutôt appliquer la méthode suivante android:paddingLeft y android:paddingRight . Les vues voisines peuvent partager les marges et les pages peuvent se chevaucher jusqu'à la moitié de la marge souhaitée.

32voto

Paul Lammertsma Points 12817

Mark Murphy a un article de blog intéressant traitant précisément de ce problème . Bien que j'aie fini par utiliser ma propre solution dans ce fil Si vous avez besoin de plus d'informations, il est intéressant de consulter le code de Dave Smith, auquel Mark fait référence dans le billet de blog :

https://gist.github.com/8cbe094bb7a783e37ad1/

Attention ! Avant d'adopter cette approche, prenez garde à certains problèmes très sérieux, mentionnés à la fin de cet article et dans les commentaires ci-dessous.

Vous allez vous retrouver avec ça :

Screenshot of Dave Smith's PagerContainer

Il fonctionne efficacement en enveloppant un ViewPager en une sous-classe de FrameLayout en lui donnant une taille spécifique, et en appelant setClipChildren(false) . Cela empêche Android de couper les vues qui dépassent les limites de l'application. ViewPager et accomplit visuellement ce que vous voulez.

En XML, c'est très simple :

<com.example.pagercontainer.PagerContainer
    android:id="@+id/pager_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#CCC">
    <android.support.v4.view.ViewPager
        android:layout_width="150dp"
        android:layout_height="100dp"
        android:layout_gravity="center_horizontal" />
</com.example.pagercontainer.PagerContainer>

Ajoutez un peu de code pour gérer les événements tactiles en dehors de l'interface utilisateur. ViewPager et l'invalidation de l'affichage lors du défilement, et vous avez terminé.

Ceci étant dit, et bien que cela fonctionne très bien en général, j'ai remarqué qu'il y a un cas limite qui n'est pas résolu avec cette construction assez simple : lorsque l'on appelle setCurrentPage() en el ViewPager . Le seul moyen que j'ai pu trouver pour résoudre ce problème était de sous-classer ViewPager lui-même et ayant son invalidate() invalide également la fonction PagerContainer .

0 votes

@Pual Lammertsma : pouvez-vous s'il vous plaît me dire où appeler invalidate() dans l'activité contenant le viewpager aussi si vous pouvez partager votre code de viewpagers ce serait génial.

0 votes

Cette technique pose divers problèmes, notamment les événements tactiles. J'ai bien peur de ne pas pouvoir partager le code car il fait partie d'un projet propriétaire, mais je vous recommande plutôt d'opter pour l'autre solution .

1 votes

D'après mon expérience, les animations/réponses de cette technique ne sont pas très nettes. Je ne sais pas si quelque chose est redessiné une fois de plus ou quoi. Je ne pense pas non plus avoir utilisé une vue de contenu très compliquée. Cela semble être une vue/composant si simple... décevant qu'Android n'ait pas de solution native non dépréciée :(

18voto

andro Points 572

Il est possible d'afficher plus d'une page sur le même écran. L'un des moyens est de surcharger la méthode getPageWidth() dans le PAgerAdapter. getPageWidth() renvoie un nombre flottant entre 0 et 1 indiquant la largeur de la page que le Viewpager doit occuper. Par défaut, la valeur est de 1. Vous pouvez donc la modifier pour obtenir la largeur que vous souhaitez. Vous pouvez en savoir plus à ce sujet aquí & projet github .

6 votes

Cette méthode fonctionne, mais n'oubliez pas qu'elle ne permet pas de centrer les pages à l'intérieur de la vue, c'est-à-dire que la page la plus à gauche sera au même niveau que le côté gauche du ViewPager.

0 votes

Alors, on peut le faire au centre ?

0 votes

Une simple ligne résout mon problème... Dans mon cas, je veux afficher 3 éléments... donc pagewidth=0.33... exemple de code pour les futurs utilisateurs @Override public float getPageWidth(int position) { return 0.33f ; }

17voto

howerknea Points 287

C'est comme ça que je l'ai eu :

<android.support.v4.view.ViewPager
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_gravity="center"
    android:layout_marginBottom="8dp"
    android:clipToPadding="false"
    android:gravity="center"
    android:paddingLeft="36dp"
    android:paddingRight="36dp"/>

et en activité, j'utilise ceci :

markPager.setPageMargin(64);

J'espère que cela vous aidera !

9voto

goldengil Points 232

J'ai eu le même problème à la seule différence que j'avais besoin d'afficher 3 pages à la fois (pages précédente, actuelle et suivante). Après une très longue recherche de la meilleure solution, je pense l'avoir trouvée. La solution est un mélange de quelques réponses ici :

Comme le dit @Paul Lammertsma réponse a souligné - le code de Dave Smith dans le blog de Mark Murphy est la base de la solution. Le seul problème pour moi était que le ViewPager n'était que sur la partie supérieure de l'écran en raison de la taille qu'ils lui donnent dans le fichier xml :

 android:layout_width="150dp"
 android:layout_height="100dp"

Ce qui n'était pas bon pour mon objectif puisque je cherchais quelque chose qui s'étale sur tout l'écran. Je l'ai donc modifié pour envelopper le contenu comme vous pouvez le voir ici :

  <com.example.nutrino_assignment.PagerContainer
    android:id="@+id/pager_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#CCC">
    <android.support.v4.view.ViewPager
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />
  </com.example.nutrino_assignment.PagerContainer>

Maintenant, j'ai perdu tout l'effet de ce que le tutoriel essayait de faire. En utilisant la méthode de @andro réponse J'ai pu afficher plus d'une page à la fois : exactement deux ! La page actuelle et la suivante. Je l'ai fait en surchargeant comme suit :

        @Override 
    public float getPageWidth(int position) {
        return(0.9f); 
    }

C'était presque ce dont j'avais besoin... (même si je pense que c'est suffisant pour ce que vous demandiez), mais pour les autres qui pourraient avoir besoin de quelque chose comme ce dont j'avais besoin : Pour la dernière partie de la solution j'ai utilisé l'idée dans cette réponse encore par @Paul Lammertsma. Dans le code de Dave Smith, vous trouverez dans le fichier onCreate cette ligne :

   //A little space between pages
    pager.setPageMargin(15);

que j'ai remplacé par :

   //A little space between pages
    pager.setPageMargin(-64);

maintenant sur la première page regarde :

|view 1|view 2|view 3|
|screen   |

alors que sur le 2ème, ça ressemble à :

|view 1|view 2|view 3|
     |screen    |

J'espère que cela aidera quelqu'un ! J'ai perdu deux jours à le faire... Bonne chance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X