web-dev-qa-db-fra.com

Alignez les vues enfant au centre de ViewPager Android.

Je dois définir la vue enfant comme centre de ViewPager et j'aimerais également montrer une partie des vues précédente et suivante aux côtés de la vue actuelle (comme l’écran actuel situé en dessous de 1). Mais actuellement, la vue actuelle commence à gauche du ViewPager (comme l’écran attendu en dessous de 2). Comment puis-je y arriver?

Voici mon code ..

MyViewPagerAdapter

public class MyViewPagerAdapter extends PagerAdapter {
    private Activity mActivity;
    private int mPageCount;
    public MyViewPagerAdapter(Activity activity,int pageCount) {
        mActivity = activity;
        mPageCount = pageCount;
    }

    @Override
    public int getCount() {
        return mPageCount;
    }

    @Override
    public boolean isViewFromObject(View view, Object obj) {
        return (view ==(View)obj);
    }

    @Override
    public Object instantiateItem(ViewGroup container,final int position) {
        ViewGroup viewGroup = (ViewGroup)mActivity.getLayoutInflater().inflate(
                R.layout.item_view, null);

        viewGroup.setBackgroundColor(randomColor());

        TextView textView = (TextView)viewGroup.findViewById(R.id.textView1);
        textView.setText("Page: "+(position+1));
        Button button = (Button) viewGroup.findViewById(R.id.button1);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(mActivity, "Hey, Its clicked!!! at page "+(position+1), Toast.LENGTH_LONG).show();
            }
        });
        container.addView(viewGroup);
        return viewGroup;
    }

    Random rnd = new Random();
    private int randomColor(){
        return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
    }

    @Override
    public void destroyItem(ViewGroup collection, int position, Object view) {
        //must be overridden else throws exception as not overridden.
        Log.d("Tag", collection.getChildCount()+"");
        collection.removeView((View) view);
    }

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

Activité principale

public class MainActivity extends Activity {
    private ViewPager viewPager;
    LinearLayout linearLayout;
    private int ID = 100; 

    private final int count = 8;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewPager = (ViewPager) findViewById(R.id.viewPager);
        linearLayout  = (LinearLayout) findViewById(R.id.indicator_layout);
        generateIndicators(count);


        MyViewPagerAdapter adapter = new MyViewPagerAdapter(this, count);
        viewPager.setAdapter(adapter);
        viewPager.setOnPageChangeListener(new OnPageChangeListener() {
            int oldPosition = 0;
            @Override
            public void onPageSelected(int position) {
                //this changes the old position's view state image
                ((TextView)linearLayout.getChildAt(oldPosition)).setText("");
                oldPosition = position;


                //this changes the current position's view state image
                ((TextView)linearLayout.getChildAt(position)).setText((position+1)+"");

            }
            //this method will be called repeatedly upto another item comes as front one(active one)
            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {


            }
            //this will be called as per scroll state
            @Override
            public void onPageScrollStateChanged(int arg0) {


            }
        });

        viewPager.setOffscreenPageLimit(4);

    }

    private void generateIndicators(int count) {
        /// Converts 14 dip into its equivalent px
        int padd = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getResources().getDisplayMetrics());

        for(int i=0;i<count;i++){
            TextView textView = new TextView(this);
            textView.setId(ID+i);
            final int currentItem = i;
            textView.setBackgroundResource(R.drawable.white_cell);
            textView.setPadding(padd,padd,padd,padd);
            /// Converts 14 dip into its equivalent px
            int size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics());
            textView.setTextSize(size);
            textView.setGravity(Gravity.CENTER);
            /// Converts 14 dip into its equivalent px
            int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, getResources().getDisplayMetrics());

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(px, px);
            linearLayout.addView(textView,params);
        }

        ((TextView)linearLayout.getChildAt(0)).setText("1");

    }





}

activity_main.xml

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context=".MainActivity" >



   <Android.support.v4.view.ViewPager
       Android:id="@+id/viewPager"
       Android:layout_width="fill_parent"
       Android:layout_height="fill_parent"
       Android:layout_alignParentLeft="true"
       Android:layout_alignParentTop="true" >
   </Android.support.v4.view.ViewPager>


   <LinearLayout
       Android:id="@+id/indicator_layout"
       Android:layout_width="wrap_content"
       Android:layout_height="wrap_content"
       Android:layout_alignParentBottom="true"
       Android:layout_centerHorizontal="true"
       Android:layout_marginBottom="19dp" >
   </LinearLayout>

</RelativeLayout>

item_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="100dp"
    Android:layout_height="match_parent"
    Android:id="@+id/root_view"
    Android:orientation="vertical" >

    <TextView
        Android:id="@+id/textView1"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:gravity="center"
        Android:text="Text"
        Android:textAppearance="?android:attr/textAppearanceLarge" />

    <Button
        Android:id="@+id/button1"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_gravity="center"
        Android:text="click me" />

</LinearLayout>

Écran actuel Current screen

écran attendu expected screen

14
Noundla Sandeep

Enfin, j'ai ajouté ma solution à cette question dans GitHub. J'ai fait quelques jolies astuces pour trouver la solution de contournement. Vous pouvez obtenir le projet à l’aide du lien ci-dessous (j’ai en fait prévu de créer un blog avec l’explication, mais je n’ai pas beaucoup de temps pour le faire). 

Voici le link ( https://github.com/noundla/Sunny_Projects/tree/master/CenterLockViewPager )

Vous devez copier les fichiers du package com.noundla.centerviewpagersample.comps dans votre projet. Et vous pouvez voir l'utilisation de ce Viewpager dans la classe MainActivity.

S'il vous plaît laissez-moi savoir si quelqu'un a des problèmes avec cela.

6
Noundla Sandeep

Pour une application, j'ai implémenté la même manière de la manière suivante, avec la variable ViewPager standard:

  • Rendre les pages en plein écran avec le contenu réel dans une disposition interne. Par exemple, définissez la disposition en plein écran sur RelativeLayout avec un arrière-plan transparent et le contenu réel sur RelativeLayout centré dans le parent. Si je me souviens bien, la raison en est qu’avec la disposition interne uniquement en tant que page, la ViewPager n’aurait pas pris toute la largeur de l’écran sur certains appareils tels que Galaxy Nexus.

  • Utilisez ViewPager.setPageMargin() pour définir une marge de page négative, c’est-à-dire le pourcentage de la page suivante/précédente que vous souhaitez afficher. Assurez-vous qu'il ne recouvre que la région transparente de la présentation plein écran parente.

  • Appelez ViewPager.setOffscreenPageLimit() pour régler le nombre de pages hors écran sur au moins 2 à partir du 1 par défaut afin de garantir une pagination fluide en créant réellement les pages hors écran. Sinon, vous verrez les pages suivantes/précédentes en cours de dessin alors qu’elles ne sont déjà que partiellement affichées à l’écran.

11
laalto

Pour ceux qui sont bouleversés par le fait que le PO n'ait pas mis à jour sa question avec la solution, voici un lien qui explique, avec un minimum d'effort, comment résoudre cela en XML: http://blog.neteril.org/blog/2013/ 10/14/Android-tip-viewpager-with-protruding-children/

En gros, lorsque vous déclarez votre viewpager en XML, attribuez-lui le même remplissage gauche et droit et définissez Android: clipToPadding = "false". (Le clipToPadding manque dans son exemple xml et est nécessaire pour obtenir cet effet)

9
Gilleland

J'ai trouvé la solution dans ce post , en dessous du code que j'ai utilisé:

// Offset between sibling pages in dp
int pageOffset = 20;

// Visible part of sibling pages at the edges in dp
int sidePageVisibleWidth = 10;

// Horizontal padding will be
int horPadding = pageOffset + sidePageVisibleWidth;

// Apply parameters
viewPager.setClipToPadding(false);
viewPager.setPageMargin(UIUtil.dpToPx(pageOffset, getContext()));
viewPager.setPadding(UIUtil.dpToPx(horPadding, getContext()), 0, UIUtil.dpToPx(horPadding, getContext()), 0);

code dpToPx:

 public static int dpToPx(int dp, Context context) {
        float density = context.getResources().getDisplayMetrics().density;
        return Math.round((float) dp * density);
    }

C'est tout ce dont vous avez besoin

2
Sergey Mohov

Vous pouvez utiliser padding pour viewPager et set clipToPadding true

Java

viewPager.setClipToPadding(false);
viewPager.setPadding(50, 0, 50, 0);

Kotlin

 viewPager.clipToPadding = false
 viewPager.setPadding(50, 0, 50, 0)
0
Rasoul Miri

Je devais centrer la page en cours dans le pageur de vue avec différentes largeurs de page , la solution avec des rembourrages n’était donc pas appropriée. Le défilement de l'utilisateur était également désactivé (il s'agissait d'un pager de vue de barre de tabulation, défilé par un autre pager de vue). Voici une solution très simple pour cela: substituez simplement la méthode ViewPager.ScrollTo comme ceci (code C #, Xamarin):

public override void ScrollTo(int x, int y)
{
    x -= (int) (MeasuredWidth * (1 - Adapter.GetPageWidth(CurrentItem)) / 2);

    base.ScrollTo(x, y);
}

Et si vous calculez la largeur de page pour chaque fragment, n'oubliez pas de les mettre en cache dans un tableau.

0