Home > database >  BottomNavigationView disappears after Fragment Transaction
BottomNavigationView disappears after Fragment Transaction

Time:10-07

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)

enter image description here

NotificationFragment (Missing Bottom Navigation) enter image description here

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"
    .../>
  • Related