I have a BottomNavigationView with 4 items inside. In one of the Fragments (HomeFragment) i've added card view with onClickListener.
After clicking the CardView, it moves the user to a new Fragment. When the Fragment inflates, the BottomNavigationView disappears completely, and the app crashes when Clicking the back button (on a null reference to the BottomNavigationView).
The error:
Attempt to invoke virtual method 'android.view.Menu com.google.android.material.bottomnavigation.BottomNavigationView.getMenu()' on a null object reference
The XML for the BottomNavigationView:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@ id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu" />
The Transaction from HomeFragment:
Fragment fragment = new NotificationsFragment();
getChildFragmentManager().beginTransaction()
.replace(R.id.fragment_home, fragment)
.addToBackStack("HomeFragment")
.commit();
Attached the screenshot of the HomeFragment with the BottomNavigationView appearing, and the new NotificationFragment - without the BottomNavigationView.
HomeFragment (With Bottom Navigation)
NotificationFragment (Missing Bottom Navigation)
Expected result:
- BottomNavigationView should appear.
EDIT #1
main_activity.xml - holds the fragment of BottomNavigationView
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@ id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@ id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu" />
<fragment
android:id="@ id/nav_host_fragment_activity_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/nav_view"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"
app:navGraph="@navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
HomeFragment.java - Initiate the Fragment Transaction
public class HomeFragment extends Fragment {
private static final int AUTOCOMPLETE_REQUEST_CODE = 3;
private static final String TAG = "HomeFragment";
private FragmentHomeBinding binding;
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
CardView card = getView().findViewById(R.id.card1);
Log.e(TAG, "Found Card!");
card.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getActivity().setContentView(R.layout.fragment_notifications);
Log.e(TAG, "Starting Login Activity");
Fragment fragment = new NotificationsFragment();
getChildFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.slide_in,R.anim.slide_in)
.replace(R.id.fragment_home, fragment)
.addToBackStack("HomeFragment")
.commit();
}
});
}
EDIT 2
Solved using the following:
NavHostFragment.findNavController(current).navigate(R.id.navigation_notifications);
where current:
Fragment current = this;
out side of the OnClickListener (current Fragment).
CodePudding user response:
The first problem is that you used getChildFragmentManager()
instead of getFragmentManager()
. To interact with the fragment container of your HomeFragment
's parent Activity
you need to use the latter, and pass in the container id as such .replace(R.id.nav_host_fragment_activity_main, fragment)
The second problem is that you are trying to manually manage your Fragment
transactions while at the same time you are using Navigation Component on your <fragment>
tag as such: app:navGraph="@navigation/mobile_navigation"
I suggest using only one of the two, in this case the Navigation Component. You can change between fragments by simply doing:
card.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e(TAG, "Starting Login Activity");
findNavController().navigate(R.id.action_home_to_notifications)
}
});
where in your mobile_navigation.xml
you'd have:
<fragment
android:id="@ id/destination_home"
android:name="...HomeFragment"
...>
<action
android:id="@ id/action_home_to_notifications"
app:destination="@id/destination_notifications"
app:enterAnim="@anim/fade_in"
app:exitAnim="@anim/fade_out"
app:popEnterAnim="@anim/fade_in"
app:popExitAnim="@anim/fade_out" />
</fragment>
<fragment
android:id="@ id/destination_notifications"
android:name="...NotificationFragment"
.../>