web-dev-qa-db-fra.com

ViewPager avec limites de page précédente et suivante

Je conçois une vue avec plusieurs pages. Je veux que les bords des pages précédentes et suivantes soient affichés comme ci-dessous et que je mette en œuvre un balayage à deux doigts pour passer d’une page à l’autre.

enter image description here

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, est-il possible de positionner une partie de ma vue en dehors de l'écran, puis de l'animer en lui donnant un effet de type ViewPager?.

Comment dois-je m'y prendre? Merci !

137
Gaurav Arora

Je me cite de n 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é qui désactivait l'écrêtage des enfants pour afficher plusieurs pages à 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. Ainsi, même si le ViewPager est concentré sur une page sélectionnée, les autres pages ayant des coordonnées au-delà de ViewPager sont toujours visibles, tant que ils correspondent à la PagerContainer. En dimensionnant le ViewPager pour qu'il soit plus petit que le PagerContainer, le ViewPager peut redimensionner ses pages à cette taille, laissant ainsi la place à d'autres pages. PagerContainer, cependant, doit aider un peu avec les événements tactiles, car ViewPager ne gérera que les événements de balayage sur ses propres limites visibles, en ignorant toutes les pages visibles des côtés.

enter image description here

97
CommonsWare

J'ai une solution similaire:

Dans la fenêtre de visualisation, définissez un remplissage gauche et droit, par exemple: 20dp. Définissez également la marge de la page sur le viewpager, par exemple. la moitié du remplissage du pager. Et n'oubliez pas de désactiver le remplissage du clip.

tilePager.setPadding(defaultGap, 0, defaultGap, 0);
tilePager.setClipToPadding(false);
tilePager.setPageMargin(halfGap);
98
Thomas R.
  1. Définissez les marges intérieure et gauche pour la vue d'ensemble. Exemple xml (page_item.xml):

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical"
    Android:paddingLeft="20dp"
    Android:paddingRight="20dp"/>
    
    <TextView
        Android:id="@+id/text1"
        Android:text="Large Text"
        Android:textAppearance="?android:attr/textAppearanceLarge" />
    
    </LinearLayout>
    
  2. Définissez ensuite la 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().getDisplayMetrics());
    mViewPager.setPageMargin(-margin);
    
  3. Optionnel. Définissez un remplissage à gauche pour le premier élément et un remplissage à droite au dernier élément pour masquer les bords vides. Vous pouvez le faire dans la classe de fragments PageAdapter ou Page.

75
SergeyA

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

45
molu2008

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

6
44kksharma

Téléchargez le code source à partir d'ici ( ViewPager avec les limites de page précédente et suivante )

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.DisplayMetrics;
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;
    String 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<Fragment> 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<Fragment> fragments;

        public MyPageAdapter(FragmentManager fm, List<Fragment> 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<Fragment> getFragments() {

        List<Fragment> fList = new ArrayList<Fragment>();

        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;
        String str = "";
        if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {
            switch (context.getResources().getDisplayMetrics().densityDpi) {
                case DisplayMetrics.DENSITY_LOW:
                    str = "small-ldpi";
                    // Log.e("small 1","small-ldpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    str = "small-mdpi";
                    // Log.e("small 1","small-mdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    str = "small-hdpi";
                    // Log.e("small 1","small-hdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    str = "small-xhdpi";
                    // Log.e("small 1","small-xhdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    str = "small-xxhdpi";
                    // Log.e("small 1","small-xxhdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    str = "small-xxxhdpi";
                    //Log.e("small 1","small-xxxhdpi");
                    value = 20;
                    break;
                case DisplayMetrics.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().getDisplayMetrics().densityDpi) {
                case DisplayMetrics.DENSITY_LOW:
                    str = "normal-ldpi";
                    // Log.e("normal-ldpi 1","normal-ldpi");
                    str_device = "normal-ldpi";
                    value = 82;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    // Log.e("normal-mdpi 1","normal-mdpi");
                    str = "normal-mdpi";
                    value = 82;
                    str_device = "normal-mdpi";
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    // Log.e("normal-hdpi 1","normal-hdpi");
                    str = "normal-hdpi";
                    str_device = "normal-hdpi";
                    value = 82;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    //Log.e("normal-xhdpi 1","normal-xhdpi");
                    str = "normal-xhdpi";
                    str_device = "normal-xhdpi";
                    value = 90;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    // Log.e("normal-xxhdpi 1","normal-xxhdpi");
                    str = "normal-xxhdpi";
                    str_device = "normal-xxhdpi";
                    value = 96;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    //Log.e("normal-xxxhdpi","normal-xxxhdpi");
                    str = "normal-xxxhdpi";
                    str_device = "normal-xxxhdpi";
                    value = 96;
                    break;
                case DisplayMetrics.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().getDisplayMetrics().densityDpi) {
                case DisplayMetrics.DENSITY_LOW:
                    str = "large-ldpi";
                    // Log.e("large-ldpi 1","normal-ldpi");
                    value = 78;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    str = "large-mdpi";
                    //Log.e("large-ldpi 1","normal-mdpi");
                    value = 78;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    //Log.e("large-ldpi 1","normal-hdpi");
                    str = "large-hdpi";
                    value = 78;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    // Log.e("large-ldpi 1","normal-xhdpi");
                    str = "large-xhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    //Log.e("large-ldpi 1","normal-xxhdpi");
                    str = "large-xxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    // Log.e("large-ldpi 1","normal-xxxhdpi");
                    str = "large-xxxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.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().getDisplayMetrics().densityDpi) {
                case DisplayMetrics.DENSITY_LOW:
                    // Log.e("large-ldpi 1","normal-ldpi");
                    str = "xlarge-ldpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    // Log.e("large-ldpi 1","normal-mdpi");
                    str = "xlarge-mdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    //Log.e("large-ldpi 1","normal-hdpi");
                    str = "xlarge-hdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    // Log.e("large-ldpi 1","normal-hdpi");
                    str = "xlarge-xhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    // Log.e("large-ldpi 1","normal-xxhdpi");
                    str = "xlarge-xxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    // Log.e("large-ldpi 1","normal-xxxhdpi");
                    str = "xlarge-xxxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_TV:
                    //Log.e("large-ldpi 1","normal-tvdpi");
                    str = "xlarge-tvdpi";
                    value = 125;
                    break;
                default:
                    str = "xlarge-unknown";
                    value = 125;
                    break;
            }
        }

        return value;
    }
}
1
Deepshikha Puri

Il y a quelque temps, j'avais besoin de cette fonctionnalité et je préparais une petite bibliothèque qui utilisait RecyclerView avec PagerSnapHelper (ajouté à la version 25.1.0 de la bibliothèque de support de la v7) au lieu du classique ViewPager:

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

Il consiste principalement en un seul fichier de classe: MetalRecyclerViewPager.Java (et deux xmls: attrs.xml et ids.xml ).

J'espère que ça aide quelqu'un :)

1