Обновить выбранное состояние навигационного ящика после обратного нажатия

Каков надлежащий способ обработки выбранного состояния ящика навигации после повторного нажатия?

У меня есть навигационный ящик с n элементами (в списке), как образец SDK в Android Studio. Когда я нажимаю на записи ящика навигации, я хочу, чтобы они были добавлены в задний стек, поэтому я могу вернуться к ним.

В onNavigationDrawerItemSelected (int pos) у меня есть

FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); if (position == 0) { transaction.replace(R.id.container, new FragmentA()); } else if (position == 1) { transaction.replace(R.id.container, new FragmentB()); } else { transaction.replace(R.id.container, new FragmentC()); } transaction.addToBackStack(null); transaction.commit(); 

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

Как я могу получить статус выбора ящика после нажатия?

Как-то мне нужно позвонить в mDrawerListView.setItemChecked (position, true); Или NavigationDrawerFragment.selectItem (int position). Но на какую позицию? Как я его помню?

Перехват с onBackPressed?

 @Override public void onBackPressed() {} 

Но как узнать, какой фрагмент активен снова? И в какую позицию это соответствует.

Есть ли какое-то простое решение, о котором я вижу? Кажется, что использование обратной связи в сочетании с навигационным ящиком и обновление статуса выбора является стандартным шаблоном.

Solutions Collecting From Web of "Обновить выбранное состояние навигационного ящика после обратного нажатия"

Этот шаблон описан в разделе « Реализация обратной навигации для фрагментов » документации «Надлежащая обратная навигация».

Если ваше приложение обновляет другие элементы пользовательского интерфейса, чтобы отразить текущее состояние ваших фрагментов, например панель действий, не забудьте обновить интерфейс, когда вы совершаете транзакцию. Вы должны обновить свой пользовательский интерфейс после изменения заднего стека в дополнение к тому, когда вы совершите транзакцию. Вы можете прослушивать, когда FragmentTransaction вернется, настроив FragmentManager.OnBackStackChangedListener :

 getSupportFragmentManager().addOnBackStackChangedListener( new FragmentManager.OnBackStackChangedListener() { public void onBackStackChanged() { // Update your UI here. } }); 

Это будет подходящее место для обновления текущей опции в навигационном ящике.

У меня было много проблем, пытаясь найти решение этой проблемы, и решение, которое я в конечном итоге использовал, на мой взгляд не «хорошо», но оно работает.

В моем приложении я закончил добавление позиции фрагментов в ящик навигации, когда я добавил фрагмент в стопку. Таким образом, я мог бы назвать setItemChecked с положением в моей onBackStackChanged (). Так что основное, что я сделал, это:

 @Override public void onBackStackChanged() { FragmentManager fm = getFragmentManager(); String name = fm.getBackStackEntryAt(fm.getBackStackEntryCount()-1).getName(); mDrawerList.setItemChecked(Integer.parseInt(name),true); } public class DrawerItemClickListener implements android.widget.AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectItem(position); } } private void selectItem(int position) { Fragment fragment; switch (position) { case 0: // Home fragment = new ContentFragment(); break; case 1: // Another fragment = new AnotherFragment(); break; default: // Logout { finish(); Intent intent = new Intent(this, StartupActivity.class); startActivity(intent); return; } } FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, fragment) .addToBackStack(Integer.toString(position)) .commit(); mDrawerList.setItemChecked(position, true); setTitle(mNavigationItems[position]); mDrawerLayout.closeDrawer(mDrawerList); } 

Основываясь на превосходном ответе @matiash (не забудьте +1 его / ее, если вы +1 мой ответ)

Для начала мы предполагаем, что мы находимся в работе

 getFragmentManager().addOnBackStackChangedListener( new FragmentManager.OnBackStackChangedListener() { public void onBackStackChanged() { // Update your UI here. } }); 

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

(От https://stackoverflow.com/a/24589081/878159 )

 Fragment f = getFragmentManager().findFragmentById(R.id.frag_container); if (f instanceof CustomFragmentClass) { // do something with f f.doSomething(); } 

Это должно сделать вас ближе. Тогда что-то вроде этого даст вам ссылку на ваш навигационный ящик:

 nav = (NavigationDrawerFragment) getFragmentManager().findFragmentById(R.id.nav); 

Затем в зависимости от того, как вы настроите код фрагмента ящика:

 nav.updateSelected(position); 

Метод updateSelected(int) будет в вашем классе NavigationDrawerFragment и может выглядеть примерно так:

 public void updateSelected(int position) { mCurrentSelectedPosition = position; if (mDrawerListView != null) { mDrawerListView.setItemChecked(position, true); } } 

ПРИМЕЧАНИЕ. Есть много способов сделать это, но это должно заставить вас начать.

Сегодня у меня была та же борьба. Я решил это, реализовав интерфейс FragmentToActivity в каждом фрагменте и в моей единственной MainActivity.

Интерфейс:

 public interface FragmentToActivity { public void SetNavState(int id); } 

Фрагменты:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ((FragmentToActivity) getActivity()).SetNavState(R.id.nav_myitemid); //just add this line } 

Основная деятельность:

 @Override public void SetNavState(int id) { NavigationView nav = (NavigationView) findViewById(R.id.nav_view); nav.setCheckedItem(id); } 

И если вы не знаете, откуда R.id.nav_myitemid , вот мой activity_main_drawer.xml :

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/nav_myitemid" android:title="@string/home" /> </group> </menu>