Програмно поверніться до попереднього фрагмента в 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();
}

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

Я знайшов функцію триггера за допомогою кнопок при натисканні кнопки в Android, але я думаю, що імітувати подію із зворотним ключем - це не правильний шлях для цього (і я також не можу змусити його працювати):

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();зробив трюк. Дякую.
Aske B.

1
Де я б поклав цей метод? У моєму вкладці слухача?
rasen58

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

1
як щодо getSupportFragmentManager ()
ViliusK

5
Не забудьте додати у свій код "addToBackStack (" тег ")". "fragmentManager.beginTransaction (). Замінити (R.id.content_frame, фрагмент) .addToBackStack (" тег "). commit ();" якщо ви пишете 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 вони не переважають надподавленою подією, і все ж вони здатні виконати резервний фрагмент. Я використав trasaction.addToBackStack (null); але нічого не відбувається. Чи можете ви пояснити, чому?
Муртаза Хуршід Хуссей

@MurtazaHussain вам, мабуть, слід задати нове запитання, якщо ви хочете допомогти з цим. Трохи важко зрозуміти, що відбувається, не дивлячись на більше коду.
Кайл Фальконер

2
У моєму випадку мені довелося це зробити fm.getBackStackEntryCount() > 1, щоб відкликати активність, коли в стеку є лише перший фрагмент.
Facundo Olano

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()волю, повернеться правдою, якщо ми додамо / оновимо фрагменти, і повернемося до поточного екрану.


7

Додайте ці рядки до методу onBackPress (). метод popBackStackImmediate () поверне вас до попереднього фрагмента, якщо у вас є якийсь фрагмент на задній стек `

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

`


5

Це рішення ідеально підходить для навігації по фрагментах на нижній панелі, коли ви хочете закрити додаток при натисканні на спинку в первинному фрагменті.

З іншого боку, коли ви відкриєте вторинний фрагмент (фрагмент у фрагменті), який у моєму коді визначений як "DetailedPizza", він поверне попередній стан первинного фрагмента. Ура!

Внутрішні заходи із натиснутою спиною ставлять так:

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();

3

Ці відповіді не спрацьовують, якщо я не додав addToBackStack () до моєї транзакції з фрагментами, але ви можете використовувати:

getActivity().onBackPressed();

від вашого будь-якого фрагмента повернутися на один крок назад;


1

Програмно поверніться до попереднього фрагмента, використовуючи наступний код.

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

1

Щоб цей фрагмент з’явився знову, просто додайте той фрагмент до заднього кута, який ви хочете, щоб він був натиснутою назад, наприклад:

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.

Отож, що я зробив - це перекрити метод onBackPress у батьківській діяльності, що містить 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)

У моєму випадку тхо, з 2 фрагментами в 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.