PopBackStack, но сохраните первый фрагмент в android

Я работаю над транзакцией фрагментов, а стопка backstack выглядит так:

fragA => fragB => fragC => fragD

Я хотел бы вернуться к fragA после того, как от fragD

fragD => onBackPress => fragA

Итак, я попробовал код вроде:

getChildFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

но он очищает все задние части, как я могу сохранить первый фрагмент в backstack? Большое спасибо

Ответ 1

например. вы можете сделать следующее:

  • добавить fragA, не добавляя его в backStack. Так что всегда в и не будет реагировать на кнопку "Назад".
  • когда вы открываете fragD, вы должны очистить фрагмент BackStack. Поэтому, когда вы нажимаете кнопку "Назад" из D frag, вы возвращаетесь к A.

P.S. Существуют и другие способы, как делать то, что вы хотите. Это зависит...

Ответ 2

Поскольку "задний стек" имеет поведение, подобное стеку... последний раз, сначала... последний фрагмент, добавленный в задний стек, сначала выскочит из предыдущего стека. Вам нужно будет выполнить поведение, которое вам требуется вручную, указав свой собственный. Это не так сложно с помощью методов класса FragmentManager.

Если вы "пометите" свои фрагменты, добавив их в транзакцию...

 fragmentTransaction.add(new FragmentA(), "FragmentA_Tag");

вы можете позже определить, какой фрагмент будет отображаться при нажатии кнопки "Назад"...

FragmentA f = fragmentManager.findFragmentByTag("FragmentA_Tag");
if(f != null){
    f.show();
}

Как вы определяете, какой фрагмент будет показан вам полностью. Вы можете отслеживать текущий видимый фрагмент, или вы можете использовать метод isHidden класса Fragment... BTW, я ' m говорит о нативных фрагментах здесь, а не поддерживает фрагмент библиотеки.

Ответ 3

Столбец содержит записи о транзакциях, а не фрагменты. Поэтому вы не должны добавлять первую запись транзакции (null → fragA) в backstack. И все остальные записи транзакций должны быть добавлены в backstack. В этом случае вы заготовки popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); android удалили все фрагменты, кроме fragA, потому что нет никаких записей о том, как был добавлен fragA.

Ответ 4

Только несколько дней назад я начинаю изучать фрагменты в Android. И я столкнулся с этой проблемой. Здесь я показываю свое решение и как я это разрешаю. Пожалуйста, исправьте, если мой код неправильный. Что мы имеем в это время? Acivity, много фрагментов и их backstack. Мы хотим открыть каждый фрагмент из меню Ящика и очистить все остальные фрагменты из backstack. Но мы должны держать только один фрагмент дома. Когда мы остаемся на домашнем фрагменте, а пользователь нажимает кнопку "Назад", приложение закрывается.

Activity.class

protected void onCreate(Bundle savedInstanceState)
{
    ...
    // adding Home fragment without adding transaction into backstack
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction ft = manager.beginTransaction();
    ft.replace(R.id.container, HomeFragment.newInstance("args"), null);
    ft.commit();
}

@Override
public void onBackPressed() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        finish();
    }
}

public void addFragmentFromMenu(Fragment fragment){
    String backStateName =  fragment.getClass().getName();
    clearBackStack();
    FragmentManager manager = getSupportFragmentManager();
    if(manager.getBackStackEntryCount()> 0)
    {
        boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);

        if (!fragmentPopped && manager.findFragmentByTag(backStateName) == null) {
            //fragment not in back stack, create it.
            addFragment(fragment, manager, backStateName);
        }
    }
    else // no fragments
    {
        addFragment(fragment, manager, backStateName);
    }
}

public void addFragment(Fragment fragment, FragmentManager manager, String backStateName)
{
    FragmentTransaction ft = manager.beginTransaction();
    ft.replace(R.id.container, fragment, backStateName);
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    ft.addToBackStack(backStateName);
    ft.commit();
}

public void clearBackStack() {
    getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}

И при нажатии на элемент меню ящика

@Override
public boolean onNavigationItemSelected(MenuItem item) {

    int id = item.getItemId();

    if (id == R.id.nav_camera) {
        addFragmentFromMenu(CameraFragment.newInstance("cam1", "cam2"));
    } else if (id == R.id.nav_gallery) {
        addFragmentFromMenu(TestFragment.newInstance("test1","test2"));
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

Ответ 5

Я сделал следующий путь. Очистите весь фрагмент, затем добавьте первый фрагмент дома

FragmentManager fm = getActivity().getSupportFragmentManager();
                    fm.popBackStack(Constants.TAG_HOME, FragmentManager.POP_BACK_STACK_INCLUSIVE);

                    ((MainActivity) activity).manageFragment(new HomeFragment(), Constants.TAG_HOME);
 //        write down below function in main activity              
     public void manageFragment(Fragment fragment, String tag) {

            FragmentManager fragmentManager = getSupportFragmentManager();
            if (!fragmentManager.popBackStackImmediate(tag, 0)) {

                FragmentTransaction ft = fragmentManager.beginTransaction();
                ft.add(R.id.content_frame, fragment, tag);
                ft.addToBackStack(tag);
                ft.commit();

            }
        }

Ответ 6

1) Добавьте первый фрагмент, используя приведенный ниже код

android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
        android.support.v4.app.FragmentTransaction ft=fm.beginTransaction();
        if (fm.findFragmentById(R.id.fragment_container) != null) {
            ft.hide(fm.findFragmentById(R.id.fragment_container));
        }
        ft.add(R.id.fragment_container, new OneFragment(),OneFragment.class.getCanonicalName())
                .addToBackStack(OneFragment.class.getCanonicalName()).commit();

2) Добавьте второй фрагмент из первого фрагмента, используя приведенный ниже код

android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
                    android.support.v4.app.FragmentTransaction ft=fm.beginTransaction();
                    if (fm.findFragmentById(R.id.fragment_container) != null) {
                        ft.hide(fm.findFragmentById(R.id.fragment_container));
                    }
                    ft.add(R.id.fragment_container,new TwoFragment(),TwoFragment.class.getCanonicalName())
.addToBackStack(TwoFragment.class.getCanonicalName()).commit();

3) Добавьте третий фрагмент из второго фрагмента, используя приведенный ниже код

android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
                android.support.v4.app.FragmentTransaction ft=fm.beginTransaction();
                if (fm.findFragmentById(R.id.fragment_container) != null) {
                    ft.hide(fm.findFragmentById(R.id.fragment_container));
                }
                ft.add(R.id.fragment_container, new ThreeFragment(),ThreeFragment.class.getCanonicalName())
                        .addToBackStack(ThreeFragment.class.getCanonicalName()).commit();

4) Добавьте фрагмент Forth из третьего фрагмента, используя приведенный ниже код

android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
                android.support.v4.app.FragmentTransaction ft=fm.beginTransaction();
                if (fm.findFragmentById(R.id.fragment_container) != null) {
                    ft.hide(fm.findFragmentById(R.id.fragment_container));
                }
                ft.add(R.id.fragment_container, new FourFragment(),ThreeFragment.class.getCanonicalName())
                        .addToBackStack(FourFragment.class.getCanonicalName()).commit();

5) onBackPressed(), пожалуйста, напишите ниже код

@Override
    public void onBackPressed() {
        hideKeyboard(MainActivity.this);
        Fragment currentFragment = this.getSupportFragmentManager().findFragmentById(R.id.fragment_container);

        if (currentFragment.getClass().getName().equalsIgnoreCase(FourFragment.class.getName())) { // Using this code come from third fragment to first fragment
            Fragment f = this.getSupportFragmentManager().findFragmentByTag(TwoFragment.class.getCanonicalName());
            if (f != null) {
                this.getSupportFragmentManager().popBackStackImmediate(f.getClass().getCanonicalName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
            }
        }else {
            super.onBackPressed();
        }
    }

Ответ 7

Просмотрев много постов, я понял это следующим образом:

в методе fragC => fragD выполните две транзакции:

1 чистая стека, fragC => fragA

2 fragA => fragD

Но при этом исходное состояние fragA может быть разрушено.

public static void changeFragCtoD(FragmentManager fm, Fragment fragD){
    fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    FragmentTransaction fragmentTransaction = fm.beginTransaction();
    fragmentTransaction
            .replace(R.id.containerViewId, new fragAClass())
            .commit();

    FragmentTransaction fragmentTransaction = fm.beginTransaction();
    fragmentTransaction
            .replace(R.id.containerViewId, fragD)
            .addToBackStack(fragD.getClass().getName())
            .commit();
}

Теперь нажатие на fragD возвращает к fragA.

Ответ 8

Помните мои слова, завершенный FragmentTransaction добавляется в backstack, а не просто в фрагмент, значит, даже если вы добавляете и удаляете фрагмент в одной транзакции, вызывая poBackStack(), сторнирует полную транзакцию. Передача тега в его аргументе выводит всю транзакцию до помеченной транзакции или даже отображает помеченную транзакцию (в случае, если FragmentManager.POP_BACK_STACK_INCLUSIVE добавлен к аргументу) Так что это больше о том, как вы его добавили, а не о том, как вы его удалили. Смотрите Выполнение транзакций с фрагментами