Замените фрагмент другим фрагментом внутри ViewPager

Я использую ViewPager вместе с FragmentPagerAdapter для размещения трех разных фрагментов.

[Fragment1][Fragment2][Fragment3]

Чего я пытаюсь добиться, так это успешно заменить Fragment1 совершенно новым фрагментом Fragment4, если конкретная задача будет выполнена успешно.

Когда я использую..

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.fragment1_layout_id, fragment4);
transaction.commit();

..фрагмент красиво заменяется и показывает Fragment4 вместо Fragment1. Хотя, как только я прокручиваю до Fragment3, а затем обратно до Fragment4, Fragment1 возвращается.

Опять же, если я использую ..

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.remove(fragment1);
transaction.commit();

..Fragment1 удаляется, и когда я возвращаюсь, Fragment4 там. Итак, проблема с этим решением заключается в том, что я не смог найти способ немедленно показать Fragment4, поскольку Fragment1 удален, даже если бы я попытался:

transaction.add(fragment4);
transaction.show(fragment4);

А вот как моя реализация FragmentPagerAdapter выглядит на данный момент без управления транзакциями:

public static class PagerAdapter extends FragmentPagerAdapter {

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

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

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = null;

        switch (position) {
        case 0:
            fragment = Fragment1.newInstance(context_);
            break;

        case 1:
            fragment = Fragment2.newInstance(context_);
            break;

        case 2:
            fragment = Fragment3.newInstance(context_);
            break;

        default:
            break;
        }

        return fragment;
    }
}

Редактировать.

Так что, похоже, я не совсем ясно выразился в своем вопросе. Я решил удалить все спагетти, которые мне удалось создать ранее, и попытался заявить, что я их не использовал (см. текст, выделенный жирным шрифтом выше).

Во всяком случае, вот что я пытался сделать внутри getItem():

@Override
public Fragment getItem(int position) {

    Fragment fragment = null;

    switch (position) {
    case 0:

        if (!app.isUserLoggedIn) {
            if (loginFragment_ == null) {
                loginFragment_ = LoginFragment.newInstance(context_);
                transaction_ = fragmentManager_.beginTransaction();

                if (logoutFragment_ != null) {
                    transaction_.remove(logoutFragment_);
                    logoutFragment_ = null;
                }

                transaction_.add(loginFragment_, "login");
                transaction_.commit();
            }

            if (fragmentManager_.findFragmentByTag("login") == null)
                fragment = LoginFragment.newInstance(context_);
            else
                fragment = fragmentManager_.findFragmentByTag("login");

        } else {
            if (logoutFragment_ == null) {                      
                logoutFragment_ = LogoutFragment.newInstance(context_);
                transaction_ = fragmentManager_.beginTransaction();

                if (loginFragment_ != null) {
                    transaction_.remove(loginFragment_);
                    loginFragment_ = null;
                }

                transaction_.add(logoutFragment_, "logout");
                transaction_.commit();
            }

            if (fragmentManager_.findFragmentByTag("logout") == null)
                fragment = LogoutFragment.newInstance(context_);
            else
                fragment = fragmentManager_.findFragmentByTag("logout");
        }
        break;

    case 1:
        fragment = HomeFragment.newInstance(context_);
        break;

    case 2:
        fragment = RegisterFragment.newInstance(context_);
        break;

    default:
        break;
    }

    return fragment;
}

С этим кодом я ничего не делаю, но если кто-то увидит, что я делаю неправильно, и захочет указать мне правильное направление, я буду очень признателен!


person velu    schedule 16.09.2011    source источник
comment
Я думаю, вам следует изменить getItem в PagerAdapter. Возвращается фрагмент, который должен быть виден.   -  person pawelzieba    schedule 16.09.2011
comment
@dziobas Именно здесь я безуспешно пытался сотворить магию, которую описал в своем вопросе.   -  person velu    schedule 16.09.2011
comment
См. мой ответ на аналогичный вопрос о том, как вставлять/заменять вкладки с помощью ViewPager и FragmentPagerAdapter.   -  person jfritz42    schedule 22.12.2012
comment
фрагмент2 вызывается, когда я нажимаю на вкладку 1, я не знаю, почему вызывается вкладка 2? ошибка адаптера?   -  person Faisal Ashraf    schedule 19.05.2015


Ответы (5)


Попробуйте использовать FragmentStatePagerAdapter.

http://android-developers.blogspot.com/2011_08_01_archive.html

потому что он удалит фрагмент, когда вы пролистываете представление (также когда вы вызываете getitem), поэтому вам не нужно явно удалять их самостоятельно.

У меня такая же проблема, у меня работает.

Я пробую ваш код и удаляю блок if (fragment!=null), и он работает.

person Ridwan Yusuf    schedule 26.09.2011
comment
Можете ли вы показать код, плз. Буду очень признателен, потому что я следовал вашим шагам и не получил того, что хотел... - person cesards; 10.10.2012

Как сказал Морици, вам нужно вызывать mAdapter.notifyDataSetChanged() всякий раз, когда вы хотите сообщить ViewPager, что фрагменты были заменены. Однако вам также необходимо переопределить абстрактную функцию getItemPosition() в вашем адаптере и возвращать POSITION_NONE при вызове со старым, чтобы быть скрытым, фрагментом в качестве аргумента. В противном случае ViewPager сохранит все текущие фрагменты.

Для получения дополнительной информации и примера кода см. этот ответ на похожий вопрос.

person wize    schedule 03.02.2012

Разве ваш оператор getItem не должен при некоторых обстоятельствах возвращать фрагмент 4 для case 0?

person Sashi Kolli    schedule 16.09.2011
comment
Да, так и должно быть, и я весь день пытался найти правильный способ сделать это. Я обновил свой вопрос и добавил, как я пытался это сделать до сих пор. - person velu; 16.09.2011

Эй, я решил эту проблему, используя список внутри моего FragmentPagerAdapter для обработки различных фрагментов, а затем мой getItem выглядит так....

    public void addScreen(String tag, Class<?> clss, Bundle args){
        if(clss!=null){
            TabInfo info = new TabInfo(tag, clss, args);
            screens.add(info);
        }
    }
@Override
    public Fragment getItem(int position) {
        TabInfo info = screens.get(position);
        return Fragment.instantiate(context, info.clss.getName(), info.args);
    }

Затем я программно удаляю/добавляю/переставляю элементы списка (фрагменты), а затем вызываю обработчик

mAdapter.notifyDataSetChanged()
person Maurycy    schedule 28.01.2012

Попробуйте установить для offScreenPageLimit значение 5 (или в зависимости от вашего варианта использования), чтобы избежать перезагрузки фрагмента, чтобы то, что вы заменили, оставалось, а не перезагружалось при пролистывании.

    mViewPager.setOffscreenPageLimit(5);
person Shangeeth Sivan    schedule 22.02.2018