【发布时间】:2018-09-12 19:34:30
【问题描述】:
我正在使用来自the following example 的BottomNavigationDrawer/BottomSheetDialog,其中BottomNavigationDrawer 在单个活动内的多个片段之间切换。
implementing the BottomNavigationDrawer时,我意识到当不使用菜单交换片段时,即通过单击片段中的按钮,this left the menu selection in an inconsistent state.另外,在主活动中使用函数触发@987654332的解决方案@ 导致崩溃。
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 为空and/or the fragment not being attached 引起的,而using getChildFragmentManager 不是正确的解决方案,因为我不使用嵌套片段,仅在单个活动中使用多个片段。
我还尝试在the onDetach is overridden to make the childFragmentManager accessible 处实施此解决方法。
This fix prevents the app from crashing with an 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)
【问题讨论】:
标签: android android-fragments navigation-drawer navigationview