web-dev-qa-db-fra.com

Pourquoi il n'est pas possible d'utiliser ViewPager dans un fragment? C'est en fait

Il existe des informations selon lesquelles il est impossible d'utiliser ViewPager au sein d'une Fragment dans de nombreuses sources telles que " Le Guide des codeurs occupés pour les développeurs Android " de Mark Murphy, ou des publications telles que this sur SO. Je suis confus parce que je n'ai pas un tel problème et que j'utilise avec succès ViewPager dans ma Fragment. La seule différence est que j'instancie une ViewPager pas dans la méthode onCreateView() mais dans onActivityCreated(). Et tout fonctionne parfaitement bien. 

La question est donc la suivante: peut-être que je ne sais simplement pas quelque chose et que cela n’est pas recommandé pour certaines raisons de créer des instanciations d’UI dans onActivityCreated()? Mais encore une fois - tout fonctionne très bien.

Voici la liste de la classe et xml:

Classe:

public class ViewPagerFragment extends Fragment {

    static final int NUM_ITEMS = 2;

    private ViewPagerAdapter mAdapter;
    private ViewPager mPager;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.view_pager_fragment, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mAdapter = new ViewPagerAdapter(getFragmentManager());

        mPager = (ViewPager) getView().findViewById(R.id.pager);
        mPager.setAdapter(mAdapter);
    }

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

        @Override
        public Fragment getItem(int num) {
            if (num == 0) {
                return new ItemsListFragment();
            } else {
                return new FavsListFragment();
            }
        }

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

Disposition:

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
              Android:layout_width="fill_parent"
              Android:layout_height="fill_parent"
              Android:orientation="vertical">

    <Android.support.v4.view.ViewPager
        Android:id="@+id/pager"
        Android:layout_width="fill_parent"
        Android:layout_height="0dp"
        Android:layout_weight="1"/>

</LinearLayout>
36
Eugene

UPDATE: Depuis que cette réponse a été écrite à l'origine, vous pouvez maintenant avoir des fragments imbriqués, ce qui signifie qu'il est possible d'avoir un ViewPager utiliser des fragments pour les pages et être dans un fragment même. Cet exemple de projet illustre la technique.

Je vous renvoie maintenant à votre réponse régulière, présentée dans son intégralité ...


En me citant du livre:

Le moyen le plus simple d’utiliser un ViewPager est d’avoir des fragments de page entrants et sortants du écran basé sur l'utilisateur glisse. Cela ne fonctionne que si le ViewPager lui-même n'est pas contenu dans un fragment, car vous ne pouvez pas avoir de fragments imbriqués à l'intérieur d'autres fragments.

Citant Dianne Hackborn

Les fragments imbriqués ne sont actuellement pas pris en charge. Essayer de placer un fragment dans l'interface utilisateur d'un autre fragment entraînera un comportement indéfini et probablement cassé.

Il est parfaitement possible de placer une ViewPager dans une Fragment, tant que le contenu de la ViewPagerne contiennent pas eux-mêmes de fragments. Étant donné que les implémentations concrètes de PagerAdapter fournies par le package de support Android utilisent des fragments, vous devez lancer votre propre fragment PagerAdapter sans-fragment pour placer le ViewPager dans un fragment.

J'essaierai de préciser ce point dans la prochaine édition du livre (à moins que vous ne soyez britannique, auquel cas je tenterai de le préciser :-).

61
CommonsWare

Pour implémenter le pageur View dans un fragment, utilisez getChildFragmentManager () au lieu de getFragmentManager () . Vous pouvez appeler setAdapter () pour le ViewPager depuis onCreateView () ou onActivityCreated () , ce n’est pas un problème.

J'espère que cela va vous aider les gars.

69
Rajkumar

Lors de l'initialisation de SetionPageAdapter pour ViewPager, utilisez "getChildFragmentManager ()".

mSectionsPagerAdapter = new SectionsPagerAdapter (getChildFragmentManager ());

4
hims_3009

il est possible d'essayer de faire ce code et d'enregistrer view_pager_fragment.xml 

<Android.support.design.widget.AppBarLayout
    Android:id="@+id/appBarLayout"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <Android.support.design.widget.TabLayout
        Android:id="@+id/tab"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" />

</Android.support.design.widget.AppBarLayout>

<Android.support.v4.view.ViewPager
    Android:id="@+id/viewpager"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

ViewPagerFragment 

ViewPager viewPager;
TabLayout tabLayout;

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

    viewPager = (ViewPager) view.findViewById(R.id.viewpager);
    tabLayout = (TabLayout) view.findViewById(R.id.tab);

    return view;
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    setupViewPager(viewPager);
    tabLayout.setupWithViewPager(viewPager);

    tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
}

private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());``

    viewPagerAdapter.addFragment(new FirstFragment(), "First");
    viewPagerAdapter.addFragment(new SecoundFragment(), "Secound");
    viewPagerAdapter.addFragment(new LoginFragment(), "Login");

    viewPager.setAdapter(viewPagerAdapter);
}

private class ViewPagerAdapter extends FragmentPagerAdapter {

    List<Fragment> fragmentList = new ArrayList<>();
    List<String> fragmentTitles = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    @Override
    public Fragment getItem(int position) {
        return fragmentList.get(position);
    }

    @Override
    public int getCount() {
        return fragmentList.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return fragmentTitles.get(position);
    }

    public void addFragment(Fragment fragment, String name) {
        fragmentList.add(fragment);
        fragmentTitles.add(name);
    }
}
0
mukesh mali