Comment implémenter un ViewPager avec différents fragments / mises en page

191

Lorsque je démarre une activité qui implémente viewpager, le viewpager a créé divers fragments. Je veux utiliser différentes mises en page pour chaque fragment, mais le problème est que le viewpager ne montre que deux mises en page au maximum (deuxième mise en page sur tous les fragments restants après 1).

Voici le code pour SwipeActivity qui implémente le viewpager:

public class SwipeActivity extends FragmentActivity
{

    MyPageAdapter pageAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_swipe);
        pageAdapter = new MyPageAdapter(getSupportFragmentManager());
        ViewPager pager=(ViewPager)findViewById(R.id.pager);
        pager.setAdapter(pageAdapter);
        ActionBar bar = getActionBar();
        bar.setDisplayHomeAsUpEnabled(true);
    }
    /**
    * Custom Page adapter
    */
    private class MyPageAdapter extends FragmentPagerAdapter
    {
        public MyPageAdapter(FragmentManager fm)
        {
            super(fm);
        }
        @Override
        public int getCount()
        {
            return 5;
        }
        @Override
        public Fragment getItem(int position)
        {
            switch(position)
            {
                case 0: return new MyFragment();
                case 1: return SecondFragment.newInstance("asdasd");
                default : return RamFragment.newInstance("s");
            }
        }
     }
}

Voici le code des fragments

public class MyFragment extends Fragment
{
   @Override
   public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup,    Bundle paramBundle)
   {
     return paramLayoutInflater.inflate(R.layout.processorlayout, paramViewGroup, false);
   }
}

J'ai utilisé 5 fragments comme celui-ci, tous ayant des mises en page différentes, mais le visualiseur n'en montre que 2 au maximum.

EDIT : code pour SecondFragment

public class SecondFragment extends Fragment
{
   public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";

  public static final SecondFragment newInstance(String paramString)
  {
    SecondFragment f = new SecondFragment();
    Bundle localBundle = new Bundle(1);
    localBundle.putString("EXTRA_MESSAGE", paramString);
    f.setArguments(localBundle);
    return f;
  }

  @Override
  public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle)
  {
     return paramLayoutInflater.inflate(R.layout.motherboardlayout, paramViewGroup, false);
  }
}
Haxor
la source
Je reçois une erreur d'incompatibilité de type. Pouvez-vous jeter un œil à mon message? stackoverflow.com/questions/28334800/…
Schardt12
Quel est donc le problème de votre code?
user1510006
Salut , vous pouvez lire ce message réponse très simple avec le code complet fourni.
Nirmal Dhara

Réponses:

518

Comme il s'agit d'une question très fréquemment posée, je voulais prendre le temps et l'effort d'expliquer en détail le ViewPager avec plusieurs fragments et mises en page. Voici.

ViewPager avec plusieurs fragments et fichiers de mise en page - Comment faire

Voici un exemple complet de la façon d'implémenter un ViewPager avec différents types de fragments et différents fichiers de mise en page.

Dans ce cas, j'ai 3 classes Fragment et un fichier de mise en page différent pour chaque classe. Afin de garder les choses simples, les mises en page de fragments ne diffèrent que par leur couleur d'arrière-plan . Bien sûr, n'importe quel fichier de mise en page peut être utilisé pour les fragments.

FirstFragment.java a une disposition d'arrière-plan orange , SecondFragment.java a une disposition d'arrière-plan vert et ThirdFragment.java a une disposition d'arrière-plan rouge . De plus, chaque Fragment affiche un texte différent, en fonction de la classe dont il provient et de l'instance dont il s'agit.

Sachez également que j'utilise le fragment de la bibliothèque de support: android.support.v4.app.Fragment

MainActivity.java (Initialise le Viewpager et a l'adaptateur pour lui comme classe interne). Encore une fois, regardez les importations . J'utilise le android.support.v4package.

import android.os.Bundle;
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.view.ViewPager;

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     

        ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
        pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
    }

    private class MyPagerAdapter extends FragmentPagerAdapter {

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int pos) {
            switch(pos) {

            case 0: return FirstFragment.newInstance("FirstFragment, Instance 1");
            case 1: return SecondFragment.newInstance("SecondFragment, Instance 1");
            case 2: return ThirdFragment.newInstance("ThirdFragment, Instance 1");
            case 3: return ThirdFragment.newInstance("ThirdFragment, Instance 2");
            case 4: return ThirdFragment.newInstance("ThirdFragment, Instance 3");
            default: return ThirdFragment.newInstance("ThirdFragment, Default");
            }
        }

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

activity_main.xml (Le fichier .xml MainActivitys) - un simple fichier de mise en page, contenant uniquement le ViewPager qui remplit tout l'écran.

<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/viewPager"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    />

Les classes Fragment, FirstFragment.java import android.support.v4.app.Fragment;

public class FirstFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.first_frag, container, false);

        TextView tv = (TextView) v.findViewById(R.id.tvFragFirst);
        tv.setText(getArguments().getString("msg"));

        return v;
    }

    public static FirstFragment newInstance(String text) {

        FirstFragment f = new FirstFragment();
        Bundle b = new Bundle();
        b.putString("msg", text);

        f.setArguments(b);

        return f;
    }
}

first_frag.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_orange_dark" >

    <TextView
        android:id="@+id/tvFragFirst"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textSize="26dp"
        android:text="TextView" />
</RelativeLayout>

SecondFragment.java

public class SecondFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.second_frag, container, false);

    TextView tv = (TextView) v.findViewById(R.id.tvFragSecond);
    tv.setText(getArguments().getString("msg"));

    return v;
}

public static SecondFragment newInstance(String text) {

    SecondFragment f = new SecondFragment();
    Bundle b = new Bundle();
    b.putString("msg", text);

    f.setArguments(b);

    return f;
}
}

second_frag.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_green_dark" >

    <TextView
        android:id="@+id/tvFragSecond"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textSize="26dp"
        android:text="TextView" />

</RelativeLayout>

ThirdFragment.java

public class ThirdFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.third_frag, container, false);

    TextView tv = (TextView) v.findViewById(R.id.tvFragThird);      
    tv.setText(getArguments().getString("msg"));

    return v;
}

public static ThirdFragment newInstance(String text) {

    ThirdFragment f = new ThirdFragment();
    Bundle b = new Bundle();
    b.putString("msg", text);

    f.setArguments(b);

    return f;
}
}

third_frag.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_red_light" >

    <TextView
        android:id="@+id/tvFragThird"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textSize="26dp"
        android:text="TextView" />

</RelativeLayout>

Le résultat final est le suivant:

Le Viewpager contient 5 fragments, les fragments 1 sont de type FirstFragment et affichent la mise en page first_frag.xml, le fragment 2 est de type SecondFragment et affiche le second_frag.xml et les fragments 3 à 5 sont de type ThirdFragment et affichent tous le third_frag.xml .

entrez la description de l'image ici

Ci-dessus, vous pouvez voir les 5 fragments entre lesquels peuvent être commutés via un balayage vers la gauche ou la droite. Un seul Fragment peut être affiché à la fois bien sûr.

Enfin et surtout:

Je vous recommande d'utiliser un constructeur vide dans chacune de vos classes Fragment.

Au lieu de transmettre des paramètres potentiels via le constructeur, utilisez la newInstance(...)méthode et le Bundlepour transmettre les paramètres.

De cette façon, s'il est détaché et rattaché, l'état de l'objet peut être stocké via les arguments. Tout comme Bundlesattaché à Intents.

Philipp Jahoda
la source
7
@PhilippJahoda excellente réponse, merci. Je voudrais mentionner une chose cependant, si le ViewPager est défini dans un Fragment, getSupportChildFragmentManager () doit être utilisé à la place de getSupportFragmentManager () lors de la création de l'adaptateur. Sinon, le code se rompt lorsque le changement d'orientation se produit.
guy.gc
5
Oui c'est correct. Mais dans mon exemple, le ViewPager est défini dans une activité, et par conséquent, getSupportFragmentManager () est approprié. De plus, la méthode getSupportChildFragmentManager () n'existe pas, je suppose que vous faites référence à getChildFragmentManager ().
Philipp Jahoda
1
Vous pouvez utiliser le ViewPager avec des fragments natifs lorsque vous utilisez le package de support v13. developer.android.com/reference/android/support/v13/app/…
Philipp Jahoda
1
à partir d'Android Lollipop 5.0, est-ce toujours valable?
Orkun Ozen
5
Dans votre méthode MyPagerAdapter -> getItem (int pos), vous obtenez toujours une nouvelle instance du fragment cible (en fonction de la valeur pos). Ainsi, chaque fois que vous faites pivoter votre appareil (changement d'orientation), la méthode getItem est invoquée et des fragments sont créés encore et encore. Mais ils sont stockés dans le gestionnaire de fragments lors de leur création. Je pense que vous devriez vérifier s'ils sont déjà dans le gestionnaire de fragments car si vous ne le faites pas, vous perdez de la mémoire. Voir pastebin.com/0bJc9mHA
rekt0x
8

Créez un tableau de vues et appliquez-le à: container.addView(viewarr[position]);

public class Layoutes extends PagerAdapter {

    private Context context;
    private LayoutInflater layoutInflater;
    Layoutes(Context context){
        this.context=context;
    }
    int layoutes[]={R.layout.one,R.layout.two,R.layout.three};
    @Override
    public int getCount() {
        return layoutes.length;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return (view==(LinearLayout)object);
    }
    @Override
    public Object instantiateItem(ViewGroup container, int position){
        layoutInflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View one=layoutInflater.inflate(R.layout.one,container,false);
        View two=layoutInflater.inflate(R.layout.two,container,false);
        View three=layoutInflater.inflate(R.layout.three,container,false);
        View viewarr[]={one,two,three};
        container.addView(viewarr[position]);
        return viewarr[position];
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object){
        container.removeView((LinearLayout) object);
    }

}
Akash Ingle
la source
Nous pouvons gonfler la mise en page dans ViewPager en créant un tableau de vues.
akash ingle
6

Code pour ajouter un fragment

public Fragment getItem(int position) {

    switch (position){
        case 0:
            return new Fragment1();

        case 1:
            return new Fragment2();

        case 2:
            return new Fragment3();

        case 3:
            return new Fragment4();

        default:
            break;
    }

    return null;
}

Créez un fichier xml pour chaque fragment, par exemple pour Fragment1, utilisez fragment_one.xml comme fichier de mise en page, utilisez le code ci-dessous dans le fichier java Fragment1.

public class Fragment1 extends Fragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_one, container, false);

        return view;

    }
}

Plus tard, vous pourrez apporter les corrections nécessaires. Cela a fonctionné pour moi.

sushh
la source
4

Exemple de base de ViewPager

Cette réponse est une simplification de la documentation , de ce tutoriel et de la réponse acceptée . Son but est de mettre en ViewPagerplace un fonctionnement le plus rapidement possible. D'autres modifications peuvent être apportées par la suite.

entrez la description de l'image ici

XML

Ajoutez les mises en page xml pour l'activité principale et pour chaque page (fragment). Dans notre cas, nous n'utilisons qu'une seule mise en page de fragment, mais si vous avez différentes mises en page sur les différentes pages, créez-en une pour chacune d'elles.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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="com.example.verticalviewpager.MainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

fragment_one.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

    <TextView
        android:id="@+id/textview"
        android:textSize="30sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />

</RelativeLayout>

Code

C'est le code de l'activité principale. Il inclut les classes PagerAdapteret en FragmentOnetant que classes internes. Si ceux-ci deviennent trop volumineux ou que vous les réutilisez à d'autres endroits, vous pouvez les déplacer vers leurs propres classes distinctes.

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

public class MainActivity extends AppCompatActivity {

    static final int NUMBER_OF_PAGES = 2;

    MyAdapter mAdapter;
    ViewPager mPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mAdapter = new MyAdapter(getSupportFragmentManager());
        mPager = findViewById(R.id.viewpager);
        mPager.setAdapter(mAdapter);
    }

    public static class MyAdapter extends FragmentPagerAdapter {
        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

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

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return FragmentOne.newInstance(0, Color.WHITE);
                case 1:
                    // return a different Fragment class here
                    // if you want want a completely different layout
                    return FragmentOne.newInstance(1, Color.CYAN);
                default:
                    return null;
            }
        }
    }

    public static class FragmentOne extends Fragment {

        private static final String MY_NUM_KEY = "num";
        private static final String MY_COLOR_KEY = "color";

        private int mNum;
        private int mColor;

        // You can modify the parameters to pass in whatever you want
        static FragmentOne newInstance(int num, int color) {
            FragmentOne f = new FragmentOne();
            Bundle args = new Bundle();
            args.putInt(MY_NUM_KEY, num);
            args.putInt(MY_COLOR_KEY, color);
            f.setArguments(args);
            return f;
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mNum = getArguments() != null ? getArguments().getInt(MY_NUM_KEY) : 0;
            mColor = getArguments() != null ? getArguments().getInt(MY_COLOR_KEY) : Color.BLACK;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_one, container, false);
            v.setBackgroundColor(mColor);
            TextView textView = v.findViewById(R.id.textview);
            textView.setText("Page " + mNum);
            return v;
        }
    }
}

Fini

Si vous avez copié et collé les trois fichiers ci-dessus dans votre projet, vous devriez pouvoir exécuter l'application et voir le résultat dans l'animation ci-dessus.

Continuer

Il y a pas mal de choses que vous pouvez faire avec ViewPagers. Consultez les liens suivants pour commencer:

Suragch
la source
3

C'est aussi bien:

<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/viewPager"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    />
public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
        pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));

    }
}


public class FragmentTab1 extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragmenttab1, container, false);
        return rootView;
    }
}

class MyPagerAdapter extends FragmentPagerAdapter{

    public MyPagerAdapter(FragmentManager fragmentManager){
        super(fragmentManager);

    }
    @Override
    public android.support.v4.app.Fragment getItem(int position) {
        switch(position){
            case 0:
                FragmentTab1 fm =   new FragmentTab1();
                return fm;
            case 1: return new FragmentTab2();
            case 2: return new FragmentTab3();
        }
        return null;
    }

    @Override
    public int getCount() {
        return 3;
    }
}
<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" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="@string/Fragment1" />

</RelativeLayout>
Ashutoshg
la source
0

Créez de nouvelles instances dans vos fragments et faites comme cela dans votre activité

 private class SlidePagerAdapter extends FragmentStatePagerAdapter {
    public SlidePagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        switch(position){
            case 0:
                return Fragment1.newInstance();
            case 1:
                return Fragment2.newInstance();
            case 2:
                return Fragment3.newInstance();
            case 3:
                return Fragment4.newInstance();


            default: break;

        }
        return null;
    }
Mwongera808
la source