Вернуться к предыдущему фрагменту на onBackPressed в Android

Я новичок в разработке Android и разрабатываю приложение с использованием макета панели навигации Android по умолчанию.

Я использую в приложении фрагмент.

Я хочу вернуться к предыдущему фрагменту при нажатии кнопки возврата на следующем фрагменте. OnBackPress должен реализовывать следующие функции

  1. Вернуться к предыдущему фрагменту при переходе к следующему фрагменту
  2. Закройте ящик, когда ящик навигации открыт
  3. Выйти из приложения при двойном нажатии назад во фрагменте1

Это мой код в MainActivity при создании нового фрагмента

// replacing the fragment
if (fragment != null) {
     FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
     ft.replace(R.id.content_frame, fragment);
  ft.commit();
}

onBackPress

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else if (getFragmentManager().getBackStackEntryCount() > 0) {
        FragmentManager fm = getSupportFragmentManager();
        fm.popBackStack();
    } else {
        super.onBackPressed();
    }
}

Но это не работает, и при нажатии кнопки «Назад» приложение закрывается, за исключением случаев, когда панель навигации открыта.


person Anuj TBE    schedule 11.11.2016    source источник


Ответы (3)


Вы не добавляете фрагмент в стопку. Тебе просто нужно сделать

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
 .replace(R.id.content_frame, fragment);
 .addToBackStack(null);
 .commit();

А поскольку Backstack фактически обрабатывается кнопкой возврата, вам не нужно обрабатывать этот сценарий в onBackPressed(), поэтому вы можете изменить его на просто:

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}
person DeeV    schedule 11.11.2016
comment
добавление .addToBackStack(null); не работает. После добавления этой строки при первом нажатии кнопки «Назад» ничего не происходит, а при втором нажатии приложение закрывается. - person Anuj TBE; 11.11.2016

Вы должны добавить Fragment из FragmentTransaction в backstack.

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
     ft.replace(R.id.content_frame, fragment).addtoBackStack(null).commit();

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

Я также не стал бы использовать replace(), потому что он невероятно глючит с backstack.

Попробуйте использовать remove(), а затем add().

person Murat Karagöz    schedule 11.11.2016

Вы должны добавить свой фрагмент в задний стек и изменить свой код следующим образом:

// this variable is needed to know how many times the back key has been pressed.
// It is incremented and reset accordingly to the logic you described
int mBackPressCount = 0;

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            // if there are no fragments in your back stack check the mBackPressCount
            if (mBackPressCount++ > 0) {
                // if you pressed back for the second time this line will terminate the activity
                super.onBackPressed();
            } 
        } else {
            // this line will pop the fragment from the back stack,
            // no need to pop it manually
            super.onBackPressed();
        }
    }
}

Добавьте фрагмент в заднюю стопку:

if (fragment != null) {
     FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
     ft.replace(R.id.content_frame, fragment);
     ft.addToBackStack(null);
     ft.commit();

     // when you add a fragment you should reset the back press count
     mBackPressCount = 0;
}

Сбросьте mBackPressCount при открытии и закрытии ящика. Если вы один раз нажали кнопку возврата и открыли ящик, счетчик нужно снова установить на 0.

DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
    @Override
    public void onDrawerSlide(View drawerView, float slideOffset) {

    }

    @Override
    public void onDrawerOpened(View drawerView) {
        mBackPressCount = 0;
    }

    @Override
    public void onDrawerClosed(View drawerView) {
        mBackPressCount = 0;
    }

    @Override
    public void onDrawerStateChanged(int newState) {

    }
});
person Massimo    schedule 11.11.2016
comment
куда вставить 3-й сегмент кода? drawerLayout является объектом DrawerLayout? - person Anuj TBE; 11.11.2016
comment
вы можете поместить его в метод onCreate. Изменен фрагмент. Однако я предлагаю использовать привязку данных, чтобы избежать всех этих вызовов findViewById (developer.android.com/topic/libraries/data-binding/index.html) - person Massimo; 11.11.2016
comment
Я сделал то, что вы сказали, но на 2-м фрагменте он принимает 3 раза обратное нажатие, и ничего не происходит, а при 3-м нажатии клавиши приложение закрывается - person Anuj TBE; 11.11.2016
comment
поведение, которое вы должны получить, будет следующим: на втором фрагменте, когда вы нажимаете назад, фрагмент выскакивает, затем, если вы нажимаете назад два раза, он должен выйти (не забудьте также не добавлять первый фрагмент в задний стек) - person Massimo; 11.11.2016