'BottomNavigationView with navigation component - selected fragment not showing

I'm currently migrating to android navigation component and cannot get the fragment transitions to work when a new item is being selected in the BottomNavigationView. I followed the instructions in the official documentation and I did not found any issues why the selected fragment is not being displayed.

In the activity in the onCreate method im setting the nav controller:

NavController navController = Navigation.findNavController(this, R.id.fragment_main_layout_nav_host);
NavigationUI.setupActionBarWithNavController(this, navController);
NavigationUI.setupWithNavController(binding.includedAppbarMain.bottomNavigationViewMainAppbar, navController);

The layout contains the nav host fragment and the BottomNavigationView:

<fragment
        android:id="@+id/fragment_main_layout_nav_host"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:navGraph="@navigation/activity_main"
        app:defaultNavHost="true"/>

<com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation_view_main_appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:menu="@menu/activity_main_bottom_navigation" />

Menu for the BottomNavigationView:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_activity_main_home"
        android:title="Home"
        android:enabled="true"
        android:icon="@drawable/ic_home_24dp"/>
    <item
        android:id="@+id/action_activity_main_notebooks"
        android:title="Notebooks"
        android:enabled="true"
        android:icon="@drawable/ic_file_24dp"/>
    <item
        android:id="@+id/action_activity_main_search"
        android:title="Search"
        android:enabled="true"
        android:icon="@drawable/ic_search_24dp"/>
</menu>

Navigation:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    app:startDestination="@id/action_activity_main_home">

    <fragment
        android:id="@+id/action_activity_main_home"
        android:name="com.inknotes.view.fragment.MainHomeFragment"
        android:label="@string/main_vertical_navigation_home"
        tools:layout="@layout/fragment_main_home" />
    <fragment
        android:id="@+id/action_activity_main_notebooks"
        android:name="com.inknotes.view.fragment.MainNotebookFragment"
        android:label="@string/main_vertical_navigation_notebooks"
        tools:layout="@layout/fragment_main_notebook" />
    <fragment
        android:id="@+id/action_activity_main_search"
        android:name="com.inknotes.view.fragment.MainSearchFragment"
        android:label="@string/main_vertical_navigation_search"
        tools:layout="@layout/fragment_main_search" />
</navigation>

The ids of the menu items and fragments are also matching and i'm running out of ideas why the new fragment is not being displayed when i select another item in the BottomNavigationView.

Edit 1:

I did some more testing and found out that popping the fragments from the backstack also does not work, maybe I have some generel issues with my nav controller?

Edit 2:

MainActivity (I removed some stuff because it would be too long):

@MainActivityScope
public class MainActivity extends AppCompatActivity implements ComponentCallbacks2, MainActivityHandler,
        SpeedDialView.OnActionSelectedListener, BottomNavigationView.OnNavigationItemSelectedListener {
    // Static variables
    public static final String EXTRA_PATH = "com.inknotes.EXTRA_PATH";

    // Injected objects
    @Inject MainHomeFragment mainHomeFragment;
    @Inject MainFolderFragment mainFolderFragment;
    @Inject MainNotebookFragment mainNotebookFragment;
    @Inject MainSearchFragment mainSearchFragment;
    @Inject MainFolderAddDialog mainFolderAddDialog;
    @Inject MainNotebookAddDialog mainNotebookAddDialog;
    @Inject MainNotebookActionModeCallback mainNotebookActionModeCallback;
    @Inject MainFolderActionModeCallback mainFolderActionModeCallback;
    @Inject FileHelper fileHelper;
    @Inject ClipboardHelper clipboardHelper;
    @Inject ViewModelProvider.Factory viewModelFactory;
    @Inject MainVerticalNavigationAdapter mainVerticalNavigationAdapter;
    @Inject XmlParser<OptionItem> xmlParser;

    // Objects
    public MainActivityComponent daggerMainActivityComponent;
    private ActivityMainBinding binding;
    private MainViewModel mainViewModel;
    private MainFolderViewModel mainFolderViewModel;
    private MainNotebookViewModel mainNotebookViewModel;
    private GestureDetectorCompat gestureDetectorCompat;
    private MenuItem searchMenuItem;
    private SelectionTracker<Long> verticalNavigationSelectionTracker;
    private NavController navController;

    // Variables
    private boolean isBackPressed = false;

    // =============================================================================================
    //region Base methods

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(
                this,
                R.layout.activity_main,
                new BindingComponent(this));
        binding.setLifecycleOwner(this);

        // Set the main dagger component
        daggerMainActivityComponent = ((InkNotesApplication) getApplication())
                .component()
                .mainActivityComponentFactory()
                .create(this);
        daggerMainActivityComponent.inject(this);

        // Get all viewModels
        mainViewModel = new ViewModelProvider(this, viewModelFactory).get(MainViewModel.class);
        mainFolderViewModel = new ViewModelProvider(this, viewModelFactory).get(MainFolderViewModel.class);
        mainNotebookViewModel = new ViewModelProvider(this, viewModelFactory).get(MainNotebookViewModel.class);

        // Set the default file
        mainViewModel.setDefaultFile(getExternalFilesDir("notes"));
        mainViewModel.setCurrentFile(getExternalFilesDir("notes"));

        gestureDetectorCompat = new GestureDetectorCompat(this, new GestureListener());

        // Set variables of binding
        binding.setHandler(this);
        binding.setViewModel(mainViewModel);

        // Setup main toolbar
        setSupportActionBar(binding.includedAppbarMain.materialToolbarMainAppbar);
        Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(false);
        getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu_24dp);

        // Setup explorer toolbar
        binding.includedAppbarFolder.materialToolbarFolder.setOnMenuItemClickListener(this::onOptionsItemSelected);

        // Setup drawer and navigation layout
        binding.navigationViewMainFolder.setVisibility(View.GONE);
        if (binding.drawerLayoutMain != null) {
            binding.drawerLayoutMain.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            binding.drawerLayoutMain.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
                @Override
                public void onDrawerSlide(View drawerView, float slideOffset) {
                    if (mainFolderActionModeCallback != null) {
                        mainFolderActionModeCallback.finish();
                    }
                }
            });
        }

        // Setup navigation
        navController = Navigation.findNavController(this, R.id.fragment_main_layout_nav_host);
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
            navController.getGraph()
        ).build();
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        if (binding.includedAppbarMain.bottomNavigationViewMainAppbar != null) {
           NavigationUI.setupWithNavController(binding.includedAppbarMain.bottomNavigationViewMainAppbar, navController);
        }

        // Set the explorer and file card fragment
        /*
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_layout_main_layout_fragment_container, mainHomeFragment).commit();*/
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_layout_main_folder_container, mainFolderFragment).commit();

        // Setup the floating action button
        binding.includedAppbarMain.speedDialViewMainAppbar.inflate(R.menu.activity_main_fab);
        binding.includedAppbarMain.speedDialViewMainAppbar.setOnActionSelectedListener(this);

        // Setup bottom navigation view
        if (binding.includedAppbarMain.bottomNavigationViewMainAppbar != null) {
            binding.includedAppbarMain.bottomNavigationViewMainAppbar.setOnNavigationItemSelectedListener(this);
        }
        // Setup the vertical navigation view
        if (binding.recyclerViewMainVerticalNavigation != null) {
            binding.recyclerViewMainVerticalNavigation.setAdapter(mainVerticalNavigationAdapter);
            List<OptionItem> items = xmlParser.parse(getResources().getXml(R.xml.menu_main_vertical_navigation), OptionItem.class);
            // Create the selection tracker
            // Add observer to the selection tracker
            mainVerticalNavigationAdapter.setSelectionTracker(verticalNavigationSelectionTracker);
            verticalNavigationSelectionTracker.select((long) R.id.action_activity_main_vertical_navigation_home);
            mainVerticalNavigationAdapter.submitList(items);

            binding.includedAppbarMain.speedDialViewMainAppbar.setVisibility(View.INVISIBLE);
            toggleFolderNavigationView(View.VISIBLE);
        }
    }

    @Override
    public void onBackPressed() {
        if (binding.drawerLayoutMain != null) {
            if (binding.drawerLayoutMain.isDrawerOpen(GravityCompat.START)) {
                binding.drawerLayoutMain.closeDrawer(GravityCompat.START);
            }
        }
        super.onBackPressed();
    }

    @Override
    public boolean onSupportNavigateUp() {
        if (binding.drawerLayoutMain != null) {
            return NavigationUI.navigateUp(navController, binding.drawerLayoutMain);
        }
        return super.onSupportNavigateUp();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        gestureDetectorCompat.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(@NonNull MotionEvent event) {
        super.dispatchTouchEvent(event);
        return gestureDetectorCompat.onTouchEvent(event);
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        selectNavigationItem(item.getItemId());
        return true;
    }
    //endregion

    // =============================================================================================
    //region Custom methods

    private void selectNavigationItem(int id) {
        switch (id) {
            case R.id.action_activity_main_home:
            case R.id.action_activity_main_vertical_navigation_home:
                //navController.navigate(R.id.action_activity_main_home);

                if (binding.drawerLayoutMain != null) {
                    binding.drawerLayoutMain.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
                }
                Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(false);
                if (searchMenuItem != null) {
                    searchMenuItem.collapseActionView();
                }
                binding.includedAppbarMain.appBarLayoutMainAppbar.setExpanded(true);
                binding.includedAppbarMain.speedDialViewMainAppbar.setVisibility(View.INVISIBLE);
                toggleFolderNavigationView(View.VISIBLE);
                break;
            case R.id.action_activity_main_notebooks:
            case R.id.action_activity_main_vertical_navigation_notebooks:
                //navController.navigate(R.id.action_activity_main_notebooks);

                if (binding.drawerLayoutMain != null) {
                    binding.drawerLayoutMain.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
                }
                Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
                if (searchMenuItem != null) {
                    searchMenuItem.collapseActionView();
                }
                binding.includedAppbarMain.appBarLayoutMainAppbar.setExpanded(true);
                binding.includedAppbarMain.speedDialViewMainAppbar.setVisibility(View.VISIBLE);
                toggleFolderNavigationView(View.GONE);
                break;
            case R.id.action_activity_main_search:
            case R.id.action_activity_main_vertical_navigation_search:
                //navController.navigate(R.id.action_activity_main_search);

                if (binding.drawerLayoutMain != null) {
                    binding.drawerLayoutMain.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
                }
                Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(false);
                if (searchMenuItem != null) {
                    searchMenuItem.expandActionView();
                }
                binding.includedAppbarMain.appBarLayoutMainAppbar.setExpanded(false);
                binding.includedAppbarMain.speedDialViewMainAppbar.setVisibility(View.INVISIBLE);
                toggleFolderNavigationView(View.VISIBLE);
                break;
        }
        isBackPressed = false;
    }

In the selectNavigationItem method you can also see that I tested to navigate manually with navController.navigate(R.id.action_activity_main_notebooks);, that worked but popping the backstack also didn't work. But setting the BottomNavigationView with NavigationUI.setupWithNavController(binding.includedAppbarMain.bottomNavigationViewMainAppbar, navController); should make it unnecessary to call navigate.

HomeFragment:

@MainActivityScope
public class MainHomeFragment extends Fragment {
    public final static String NAME = "MainHomeFragment";

    @Inject
    public MainHomeFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_main_home, container, false);
    }
}

NotebookFragment:

@MainActivityScope
public class MainNotebookFragment extends Fragment {
    // Static variables
    public final static String NAME = "MainNotebookFragment";
    private static final String ARG_COLUMN_COUNT = "column-count";

    // Injected objects
    @Inject ViewModelProvider.Factory viewModelFactory;
    @Inject MainNotebookAdapter mainNotebookAdapter;
    @Inject MainNotebookItemTouchHelperCallback mainNotebookItemTouchHelperCallback;

    // Objects
    private RecyclerView recyclerView;
    private MainNotebookViewModel mainNotebookViewModel;

    // Variables
    private int columnCount = 4;

    @Inject
    public MainNotebookFragment() {
    }

    // =============================================================================================
    //region Base methods

    @Override
    public void onCreate(Bundle savedInstanceState) {
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            columnCount = getResources().getInteger(R.integer.column_count_portrait);
        } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            columnCount = getResources().getInteger(R.integer.column_count_landscape);
        }
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_main_notebook, container, false);

        ((MainActivity) requireActivity()).daggerMainActivityComponent.inject(this);
        mainNotebookViewModel = new ViewModelProvider(requireActivity(), viewModelFactory).get(MainNotebookViewModel.class);
        if (getArguments() != null) {
            columnCount = getArguments().getInt(ARG_COLUMN_COUNT);
        }

        // Set the mainNotebookAdapter
        if (view instanceof RecyclerView) {
            Context context = view.getContext();
            recyclerView = (RecyclerView) view;
            if (columnCount <= 1) {
                recyclerView.setLayoutManager(new LinearLayoutManager(context));
            } else {
                recyclerView.setLayoutManager(new GridLayoutManager(context, columnCount));
            }
            recyclerView.setAdapter(mainNotebookAdapter);
        }

        // Set the item touch helper
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(mainNotebookItemTouchHelperCallback);
        itemTouchHelper.attachToRecyclerView(recyclerView);

        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mainNotebookViewModel.getItems().observe(
                getViewLifecycleOwner(),
                fileCardItems -> mainNotebookAdapter.setItems(fileCardItems)
        );

        mainNotebookViewModel.getSelectedItems().observe(
                getViewLifecycleOwner(),
                selectedExplorerItems -> mainNotebookAdapter.setSelectedItems(selectedExplorerItems)
        );

        mainNotebookViewModel.getQueryText().observe(
                getViewLifecycleOwner(),
                queryText -> mainNotebookAdapter.getFilter().filter(queryText)
        );
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!EventBus.getDefault().isRegistered(mainNotebookAdapter)) {
            EventBus.getDefault().register(mainNotebookAdapter);
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        EventBus.getDefault().unregister(mainNotebookAdapter);
    }
    //endregion
}

SearchFragment:

@MainActivityScope
public class MainSearchFragment extends Fragment {
    public final static String NAME = "MainSearchFragment";

    @Inject
    public MainSearchFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_main_search, container, false);
    }
}


Solution 1:[1]

I finally found the solution, the problem was the onNavigationItemSelected function. So either removing those two parts from the MainActivity resolves the issue:

if (binding.includedAppbarMain.bottomNavigationViewMainAppbar != null) {    
 binding.includedAppbarMain.bottomNavigationViewMainAppbar.setOnNavigationItemSelectedListener(this);
}
...
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    selectNavigationItem(item.getItemId());
    return true;
}

Or what I did, because I stil need the function, return NavigationUI.onNavDestinationSelected(item, navController) instead of true.

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    selectNavigationItem(item.getItemId());
    return NavigationUI.onNavDestinationSelected(item, navController);
}

Solution 2:[2]

Finally got resolved my issue , when i am using a nav graph where many fragment and actions occur for a bottom navigation component where only 5 menu available .

my issue was when i am visit any menu then it show active stag but when i visit twise which is already visit then no active stag show .. Means that no active color showing after navigating fragment.

Fixed with this solution :-

app:popUpTo="@id/homeFragment" app:popUpToInclusive="true"

<fragment
        android:id="@+id/addAccountFragment"
        android:name="app.ph7.doctor.ui.screens.home.addAccount.AddAccountFragment"
        android:label="AddAccountFragment"
        tools:layout="@layout/fragment_add_account">
        <action
            android:id="@+id/action_addAccountFragment_to_accDetailsFragment"
            app:destination="@id/accDetailsFragment" />
        <action
            android:id="@+id/action_addAccountFragment_to_notificationFragment"
            app:destination="@id/notificationFragment" />
        <action
            android:id="@+id/action_addAccountFragment_to_appointmentFragment"
            app:destination="@id/appointmentFragment"
            app:popUpTo="@id/homeFragment"
            app:popUpToInclusive="true" />
    </fragment>

Here homefragment is startDestination

<navigation
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/dashboard_navigation"
        app:startDestination="@id/homeFragment">

Hope your problem resolved ..

Solution 3:[3]

As official document says -

NavController manages app navigation within a NavHost.

Apps will generally obtain a controller directly from a host, or by using one of the utility methods on the Navigation class rather than create a controller directly.

When you are creating your navController, make sure you are assigning it the id of your navigation host fragment. This is how you are creating your navController.

NavController navController = Navigation.findNavController(this, R.id.fragment_main_layout); 
// issue here, use R.id.fragment_main_layout_nav_host

while the id of nav host fragment in your xml is -

<fragment>
    android:id="@+id/fragment_main_layout_nav_host"
    .....
</fragment>


  

Make sure you are using same id.

Happy Coding !!

Solution 4:[4]

You are using the wrong id of the host fragment when initializing the NavController

You need to replace

NavController navController = Navigation.findNavController(this, R.id.fragment_main_layout);

with

NavController navController = Navigation.findNavController(this, R.id.fragment_main_layout_nav_host);

Solution 5:[5]

``Did you initialize BottomNavigationView

BottomNavigationView bottomNavigationView =binding.bottomNavigationAppBar

and call bottomNavigationView in

NavigationUI.setupWithNavController(bottomNavigationView,
            navController);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Timo S.
Solution 2 Surajkaran Meghwanshi
Solution 3
Solution 4 Zain
Solution 5 ismailfarisi