Я использую BottomNavigationDrawer
/ BottomSheetDialog
из в следующем примере , где BottomNavigationDrawer
переключается между несколькими фрагментами внутри одного действия.
В то время как реализует BottomNavigationDrawer
, я понял, что, когда фрагменты менялись местами без использования меню, то есть путем нажатия кнопки во фрагменте, это оставляло выбор меню в несогласованном состоянии. . Кроме того, решение использовать функцию в основной активности для запуска FragmentTransaction
вызвало сбои.
public void resetNavDefault(){
if(fragment == null) {
fragment = new BottomNavigationDrawerFragment();
navigationView = fragment.getNavigationView();
} else navigationView = fragment.getNavigationView();
//navigationView.getMenu().getItem(0).setChecked(true);
Log.d(TAG, "resetNavDefault: setting check");
MenuItem item = navigationView.getMenu().getItem(0);
navigationView.getMenu().performIdentifierAction(item.getItemId(), 0);
}
Я понял, что это было вызвано тем, что getSupportFragmentManager
был нулевым и / или фрагмент не был прикреплен , а с использованием getChildFragmentManager
не было правильным решением, как я не использовать вложенные фрагменты, только несколько фрагментов в одном упражнении.
Я также попытался реализовать этот обходной путь, где onDetach
переопределяется, чтобы childFragmentManager
был доступен .
Это исправление предотвращает сбой приложения с NPE (из-за условия if (!isAdded()) return;
), но оставляет кнопку, которая запускает новый фрагмент, без ответа (кнопка не работает ).
Как перемещаться между двумя фрагментами, используя FragmentTransaction
, не вызывая NPE и не оставляя пункт меню в несогласованном состоянии?
Моя BottomNavigationDrawer
реализация выглядит следующим образом:
BottomNavigationDrawer
public class BottomNavigationDrawerFragment extends BottomSheetDialogFragment {
BottomNavigationDrawerFragment fragment;
public NavigationView navigationView;
ImageView close, menu;
Statuser statuser;
RevivDatabase database;
String email, fname, lname;
TextView txtUsername, txtEmail;
private static String TAG = "BottomNavDrawerFragment";
public BottomNavigationDrawerFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_bottomsheet, container, false);
txtUsername = view.findViewById(R.id.txtUsername);
txtEmail = view.findViewById(R.id.txtEmail);
navigationView = view.findViewById(R.id.navigation_view);
database = RevivDatabase.getDatabase(getActivity());
statuser = database.revivDao().getUserDetails();
fname = statuser.getFname();
lname = statuser.getLname();
email = statuser.getEmail();
txtEmail.setText(email);
txtUsername.setText(fname+" "+lname);
setRetainInstance(true);
close = view.findViewById(R.id.imgClose);
fragment = this;
close.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
fragment.dismiss();
}
});
navigationView.setItemIconTintList(null);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
menuItem.setChecked(true);
int id = menuItem.getItemId();
FragmentManager manager;
try {
manager = getActivity().getSupportFragmentManager();
} catch (NullPointerException e) {
if (!isAdded()) return false;
manager = getChildFragmentManager();
Log.e(TAG, "onNavigationItemSelected: ", e);
}
switch (id){
case R.id.app_bar_incident:
navigationView.getMenu().findItem(id).setChecked(true);
manager.beginTransaction().replace(R.id.containerFrameLayout, new FragmentRevivIncidentDashboard()).commit();
Toast.makeText(getContext(), "Request Incident", Toast.LENGTH_SHORT).show();
fragment.dismiss();
break;
case R.id.app_bar_housecall:
navigationView.getMenu().findItem(id).setChecked(true);
manager.beginTransaction().replace(R.id.containerFrameLayout, new FragmentRevivHousecallDashboard()).commit();
fragment.dismiss();
Toast.makeText(getContext(), "Request Housecall", Toast.LENGTH_SHORT).show();
break;
case R.id.settings:
navigationView.getMenu().findItem(id).setChecked(true);
manager.beginTransaction().replace(R.id.containerFrameLayout, new FragmentRevivSettingsMain()).commit();
Toast.makeText(getActivity().getApplicationContext(), "Settings", Toast.LENGTH_SHORT).show();
fragment.dismiss();
break;
}
return true;
}
});
return view;
}
@Override
public void onDetach() {
super.onDetach();
try {
Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
childFragmentManager.setAccessible(true);
childFragmentManager.set(this, null);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public NavigationView getNavigationView() {
return navigationView;
}
}
Мое сообщение об ошибке
09-13 00: 26: 32.996 28025-28025 / com.package.name E / AndroidRuntime:
ФАТАЛЬНОЕ ИСКЛЮЧЕНИЕ: главная
Процесс: com.package.name, PID: 28025
java.lang.IllegalStateException: фрагмент еще не был прикреплен.
на android.support.v4.app.Fragment.instantiateChildFragmentManager (Fragment.java:2386)
на android.support.v4.app.Fragment.getChildFragmentManager (Fragment.java:842)
в com.package.name.Fragments.BottomNavigationDrawerFragment $ 2.onNavigationItemSelected (BottomNavigationDrawerFragment.java:108)
на android.support.design.widget.NavigationView $ 1.onMenuItemSelected (NavigationView.java:170)
на android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected (MenuBuilder.java:840)
на android.support.v7.view.menu.MenuItemImpl.invoke (MenuItemImpl.java:158)
на android.support.v7.view.menu.MenuBuilder.performItemAction (MenuBuilder.java:991)
на android.support.v7.view.menu.MenuBuilder.performItemAction (MenuBuilder.java:981)
на android.support.v7.view.menu.MenuBuilder.performIdentifierAction (MenuBuilder.java:977)
в com.package.name.Reviv.resetNavDefault (Reviv.java:644)
в com.package.name.Fragments.FragmentRevivSettingsMain $ 1.onClick (FragmentRevivSettingsMain.java:77)
на android.view.View.performClick (View.java:6303)
на android.view.View $ PerformClick.run (View.java:24828)
на android.os.Handler.handleCallback (Handler.java:789)
на android.os.Handler.dispatchMessage (Handler.java:98)
на android.os.Looper.loop (Looper.java:164)
на android.app.ActivityThread.main (ActivityThread.java:6798)
в java.lang.reflect.Method.invoke (родной метод)
на com.android.internal.os.Zygote $ MethodAndArgsCaller.run (Zygote.java:240)
на com.android.internal.os.ZygoteInit.main (ZygoteInit.java:767)