Программно вернуться к предыдущему фрагменту в backstack


218

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

private void animateToFragment(Fragment newFragment, String tag) {
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, newFragment, tag);
    ft.addToBackStack(null);
    ft.commit();
}

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

Я обнаружил, что функциональность Trigger back-button при нажатии кнопки в Android, но я думаю, что имитация события back back не является правильным способом (и я тоже не могу заставить его работать):

dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));

Звонок finish()просто закрывает занятие, которое мне не интересно.

Есть ли лучший способ сделать это?

Ответы:


354

Посмотрите на getFragmentManager().popBackStack()методы (есть несколько на выбор)

http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack ()


91
getFragmentManager().popBackStackImmediate();сделал свое дело. Спасибо.
Аске Б.

1
Где бы я положил этот метод, хотя? В моей вкладке слушатель?
rasen58

1
не видя код, трудно сказать ... но он должен идти в разделе кода, который выполняется, когда вы хотите «закрыть» текущий фрагмент и вернуться к предыдущему фрагменту.
застрял

1
как насчет getSupportFragmentManager ()
ViliusK

5
Не забудьте добавить «addToBackStack (« tag »)» в ваш код. "fragmentManager.beginTransaction () заменить (R.id.content_frame, фрагмент) .addToBackStack (" метки ") совершить ();" . если вы напишите addToBackStack (null), он будет обрабатывать его сам, но если вы дадите тег, вы должны обработать его вручную.
Халед Саиф

129

Чтобы уточнить другие предоставленные ответы, это мое решение (помещено в упражнение):

@Override
public void onBackPressed(){
    FragmentManager fm = getFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        Log.i("MainActivity", "popping backstack");
        fm.popBackStack();
    } else {
        Log.i("MainActivity", "nothing on backstack, calling super");
        super.onBackPressed();  
    }
}

5
и почему это происходит. В примере фрагмента developer.android.com/training/basics/fragments/index.html они не перезаписывают событие onbackpressed, и, тем не менее, они могут сделать фрагмент обратно. Я использовал trasaction.addToBackStack (null); но ничего не происходит Вы можете объяснить, почему?
Муртаза Хуршид Хуссейн

@MurtazaHussain, возможно, вам следует задать новый вопрос, если вы хотите помочь с этим. Немного трудно понять, что происходит, не глядя на больше кода.
Кайл Фалконер

2
В моем случае я должен был сделать это fm.getBackStackEntryCount() > 1, чтобы отозвать действие, когда в стеке есть только первый фрагмент.
Факундо Олано

3
Android уже делает это за вас: «Когда в заднем стеке есть объекты FragmentTransaction, и пользователь нажимает кнопку« Назад », FragmentManager извлекает самую последнюю транзакцию из заднего стека и выполняет обратное действие (например, удаление фрагмента, если транзакция добавил это). (Источник)
artkoenig

29

Когда мы обновляем / добавляем фрагменты,

Должен включать .addToBackStack().

getSupportFragmentManager().beginTransaction()
    .add(detailFragment, "detail") // Add this transaction to the back stack (name is an optional name for this back stack state, or null).
    .addToBackStack(null)
    .commit();

После этого, если мы дадим getFragments.popBackStackImmediate(), вернется true, если мы добавим / обновим фрагменты и вернемся к текущему экрану.


7

Добавьте эти строки в ваш метод onBackPressed (). Метод popBackStackImmediate () вернет вас к предыдущему фрагменту, если у вас есть какой-либо фрагмент в заднем стеке `

if(getFragmentManager().getBackStackEntryCount() > 0){
     getFragmentManager().popBackStackImmediate();
}
else{
    super.onBackPressed();
}

`


5

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

С другой стороны, когда вы открываете вторичный фрагмент (фрагмент во фрагменте), который в моем коде определен как «DetailPizza», он вернет предыдущее состояние первичного фрагмента. Ура!

Внутри деятельности на спине нажми поставь вот это:

Fragment home = getSupportFragmentManager().findFragmentByTag("DetailedPizza");

if (home instanceof FragmentDetailedPizza && home.isVisible()) {
    if (getFragmentManager().getBackStackEntryCount() != 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
} else {
    //Primary fragment
    moveTaskToBack(true);
}

И запустите другой фрагмент так:

Fragment someFragment = new FragmentDetailedPizza();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
transaction.addToBackStack("DetailedPizza");
transaction.commit();

4

Эти ответы не работают, если у меня нет addToBackStack (), добавленной к моей транзакции фрагмента, но вы можете использовать:

getActivity().onBackPressed();

от любого вашего фрагмента, чтобы вернуться на один шаг назад;


1

Программно вернуться к предыдущему фрагменту, используя следующий код.

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();

1

Чтобы сделать этот фрагмент снова, просто добавьте этот фрагмент в backstack, который вы хотите вернуть обратно нажатием, например:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Fragment fragment = new LoginFragment();
        //replacing the fragment
        if (fragment != null) {
            FragmentTransaction ft = ((FragmentActivity)getContext()).getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.addToBackStack("SignupFragment");
            ft.commit();
        }
    }
});

В приведенном выше случае, я открываю, LoginFragmentкогда Button buttonнажата, прямо сейчас пользователь находится в SignupFragment. Итак, если addToBackStack(TAG)вызывается, где TAG = "SignupFragment", то, когда нажата кнопка «назад» LoginFragment, мы возвращаемся к SignUpFragment.

Удачного кодирования!


Я думаю, TAG не влияет, это может быть даже ноль.
CoolMind

1

Добавляя fragment_tran.addToBackStack(null) последний фрагмент, я могу вернуться к последнему фрагменту.

добавление нового фрагмента :

view.findViewById(R.id.changepass).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container, new ChangePassword());
            transaction.addToBackStack(null);
            transaction.commit();
        }
    });

1

Я пришел сюда в поисках или той же идеи, и в то же время я придумал собственную, которая, я считаю, не так уж плоха и работает, если с ViewPager.

Итак, что я сделал, это переопределил метод onBackPressed в родительском действии, которое содержит viewPager, и установил его так, чтобы он всегда возвращался назад минус 1 позиция, пока не достигнет первого фрагмента, а затем закроет действие.

@Override
public void onBackPressed() {
    if(viewPager.getCurrentItem()>0){
        viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
    } else {
        super.onBackPressed();
        this.close();
    }
}

private void close(){
    this.finish();
}

Это может иметь недостатки, как если бы он возвращался назад только в одну сторону каждый раз, так что он может работать не очень хорошо, если есть вкладки и вы переключаете позиции с пропущенными фрагментами (переход от 0 до 2, а затем нажатие назад приведет вас к 1 вместо 0)

В моем случае, с двумя фрагментами в viewPager без вкладок, он прекрасно справляется со своей задачей.


На подобный вопрос уже дан ответ. stackoverflow.com/questions/10863572/…
AtifSayings

0

Попробуйте код ниже:

@Override
    public void onBackPressed() {
        Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.container);
        if (myFragment != null && myFragment instanceof StepOneFragment) {
            finish();
        } else {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportFragmentManager().popBackStack();
            } else {
                super.onBackPressed();
            }
        }
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.