0

I have a strange problem regarding a BottomNavigationBar which I could not solve altough having spent a huge amount of time into it. When I use it in the 'recommended' way (from many tutorials) it just does not navigate.

So what do I mean by 'recommended' way: I have a single acticity with a navHostFragment called 'MainActivity'. This main activity has a XML layout file in which I put the BottomNavigationBar. The BottomNavigationBar also has a XML layout file. Now I have a Fragment called 'FR_Menu' with a Java file and a XML layout file. I also have a NavGraph. In the XML layout of the Fragment 'FR_Menu' I do not use the BottomNavigationBar and in the Java class I do not instantiate the BottomNavigationBar as I have already done this in the main Activity. But using this approach the Navigation does not work. Altough the BottomNavigationBar is correctly displayd in the Fragment 'FR_Menu', when clicking on the Bottom just nothing happens.

Now here come the strange thing. When I use the code as posted, but not put the BottomNavigationBar in the XML layout file of the main activity and instead put it separately in every XML-layout file of all Fragments (in this example the fragment 'FR_Menu') and when I also instantiate the BottomNavigationBar in every Java file of each Fragment (in this example the fragment 'FR_Menu'), then the Navigation works perfectly. So with this approach I have to put the BottomNavigationBar in every XML layout file of the fragments and also I have to instantiate the BottomNavigationBar in every Java file of the Fragments. I know that normally using the Jetpack Navigation components, this should not be the case and instead I should only have to instantiate once in the MainActivity as the BottomNavigationBar should only be added to the XML layout file of the MainActivity.

Does anyone have an idea what goes wrong when I am trying to implement the 'recommended' approach? The names are all correct (maybe there is a small error in my shown example because I had to simplify and adjust it a little bit), because when using the second approach (putting the BottomNavigationBar in every XML-layout file and in every Java file of the fragments) the navigation works perfectly (I also tried it with multiple items and destinations).

I have really spent quite much time on that and I could not figure out what my mistake it. Because of this I would highly appreciate every comment and would be quite thankful for your help.

Does anyone have an idea what the reason for this strange behaviour might be?

Java code of the 'MainActivity':

package com.example.td.bapp;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.td.bapp.databinding.ActivityMainBinding;


public class MainActivity extends AppCompatActivity  {

   
    private  ActivityMainBinding binding;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
       


    }

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        binding = ActivityMainBinding.inflate(inflater, container, false);
        NavController navController = Navigation.findNavController(this, R.id.navHostfragment);
        NavigationUI.setupWithNavController(binding.bottomNavigation,navController );
        setContentView(binding.getRoot());
        return binding.getRoot();
    }

}

XML layout file of the 'MainActivity':

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    tools:ignore="ExtraText">


    <fragment
        android:id="@+id/navHostfragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        app:labelVisibilityMode="labeled"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorGreen"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/bottom_navigation"
        app:itemIconTint="@color/colorPrimaryDark"
        app:itemTextColor="@color/colorAccent"
        />


</androidx.constraintlayout.widget.ConstraintLayout>

XML-layout file of BottomNavigationBar:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">


    <item
        android:id="@+id/FR_LanguageSelection"
        android:icon = "@drawable/ic_add_circle_full"
        android:title = "Language" />





</menu>

Java file of the Fragment 'FR_Menu'

package com.example.td.bapp;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;

import com.example.td.bapp.databinding.ActivityMainBinding;
import com.example.td.bapp.databinding.FragmentMenuBinding;


public class FR_Menu extends Fragment implements View.OnClickListener {


    // TODO: Rename and change types of parameters



    public FR_Menu() {

    }


    public static FR_Menu newInstance(String param1, String param2) {
        FR_Menu fragment = new FR_Menu();
        Bundle args = new Bundle();
        fragment.setArguments(args);
        return fragment;
    }

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


    }

    private FragmentMenuBinding binding;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // return inflater.inflate(R.layout.fragment_menu, container, false);
        binding = FragmentMenuBinding.inflate(inflater, container, false);


        /*
       // IMPORTANT REMARK: When I use the following code in the second option this in the second option,
       with the BottomNavigationBar in the XML document, the navigation works well


        NavController navController = Navigation.findNavController(getActivity(), R.id.navHostfragment);
        NavigationUI.setupWithNavController(binding.bottomNavigation,navController );
    */

        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        binding.imageButton_A.setOnClickListener(this);
        binding.imageButton_B.setOnClickListener(this);


    }

    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }


    @Override
    public void onClick(View view) {



        if(view.getId() == R.id.imageButton_A) {
            String argument = DataBaseEntries.A;

            FR_MenuDirections.ActionFRMenuToFRGenericD action =
                    FR_MenuDirections.actionFRMenuToFRGenericD(argument);
            Navigation.findNavController(view).navigate(action);
        }


        if(view.getId() == R.id.imageButton_B) {
            String argument = DataBaseEntries.B;

            FR_MenuDirections.ActionFRMenuToFRGenericD action =
                    FR_MenuDirections.actionFRMenuToFRGenericD(argument);
            Navigation.findNavController(view).navigate(action);
        }







    }
}

Here is the XML layout file of the fragment 'FR_Menu'

<?xml version="1.0" encoding="utf-8"?>


<androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">



    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar_mainActivity"
        android:layout_width="match_parent"
        android:layout_height="135dp"
        android:background="#435cb53f"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:titleTextColor="@android:color/holo_green_light">

        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:gravity="center"
            android:layout_gravity="center"
            android:textColor="@android:color/white"
            android:textSize="24sp"
            android:text="Menu" />
    </androidx.appcompat.widget.Toolbar>

    <ScrollView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="10dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/toolbar_mainActivity">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            tools:context=".MainActivity"
            tools:ignore="ExtraText">


            <ImageButton
                android:id="@+id/imageButton_A"
                android:layout_width="0dp"
                android:layout_height="128dp"
                android:background="#00000000"
                android:scaleType="fitCenter"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@id/imageButton_B"
                app:layout_constraintHorizontal_chainStyle="spread"
                app:layout_constraintHorizontal_weight="1"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/menu_A" />

            <ImageButton
                android:id="@+id/imageButton_B"
                android:layout_width="0dp"
                android:layout_height="128dp"
                android:layout_marginTop="12dp"
                android:background="#00000000"
                android:scaleType="fitCenter"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_weight="1"
                app:layout_constraintStart_toEndOf="@id/imageButton_A"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/menu_B" />






        </androidx.constraintlayout.widget.ConstraintLayout>
    </ScrollView>




</androidx.constraintlayout.widget.ConstraintLayout>

XML code of the NavGraph

<?xml version="1.0" encoding="utf-8"?>
<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/nav_graph"
    app:startDestination="@id/FR_LanguageSelection">

    <fragment
        android:id="@+id/FR_Menu"
        android:name="com.example.td.bapp.FR_Menu"
        android:label="FR_Menu"
        tools:layout="@layout/fragment_menu" >
        <action
            android:id="@+id/action_FR_Menu_to_FR_LanguageSelection"
            app:destination="@id/FR_LanguageSelection" />
    </fragment>

    <fragment
        android:id="@+id/FR_LanguageSelection"
        android:name="com.example.td.bapp.FR_LanguageSelection"
        android:label="FR_LanguageSelection" >
        <action
            android:id="@+id/action_FR_LanguageSelection_to_FR_Menu"
            app:destination="@id/FR_Menu" />
    </fragment>


</navigation>
9
  • So just to confirm, your menu XML has android:id="@+id/FR_LanguageSelection", but your navigation graph XML has a completely different ID in android:id="@+id/FR_Menu"? How are you expecting those two to be linked together if they don't match? Commented Jan 22, 2021 at 19:36
  • Thanks ianhanniballake for your comment. I do not kow if I understand your remark correctly. My FR_Menu XML does not have "android:id="@+id/FR_LanguageSelection" as you posted
    – VanessaF
    Commented Jan 22, 2021 at 20:56
  • When I said "menu XML", I meant the menu XML associated with your bottom navigation bar. Commented Jan 22, 2021 at 20:58
  • Ah okay, yes. There I have what you posted. But still I do not understand why this is a problem? As stated in my post, when using the approach of inserting the BottomNavigationBar in every XML and Java File of each Fragment, the navigation works
    – VanessaF
    Commented Jan 22, 2021 at 21:01
  • I am using a single activity multiple fragments approach for my app. When I put the BottomNavigationBar in the single activity, it just does not navigate. However, when putting it in every Fragment (both XML and Java file) then it navigates correctly.
    – VanessaF
    Commented Jan 22, 2021 at 21:05

1 Answer 1

1

onCreateView is a method of a Fragment, not a method on Activity, so your method in your MainActivity isn't ever called by the framework.

In fact, that code isn't what you'd use in an Activity at all as per the View Binding documentation.

Therefore your MainActivity should instead look like:

public class MainActivity extends AppCompatActivity  {
   
    private  ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Inflate, and then call setContentView() on the returned view root
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        
        NavController navController = Navigation.findNavController(this,
            R.id.navHostfragment);
        NavigationUI.setupWithNavController(binding.bottomNavigation, navController);
    }
}
24
  • Thanks for the answer ianhanniballake. Unfortunately my App can't be started with your suggested code. When I use your suggested code I get an error message before building the app "Cannot resolve method 'setContentView' in 'ActivityMainBinding'".
    – VanessaF
    Commented Jan 26, 2021 at 21:57
  • Because of this I replaced the databinding line - as suggested in your posted link - by "binding = ActivityMainBinding.inflate(getLayoutInflater());". Now the App can be built but when I now start the app I get immediately an error "IllegalArgumentException: ID does not reference a View inside this Activity" caused by the line " NavController navController = Navigation.findNavController(this, R.id.navHostfragment);"
    – VanessaF
    Commented Jan 26, 2021 at 21:57
  • Updated the code - it is DataBindingUtil.setContentView. If you only call inflate(), but not setContentView(), then yeah, the findViewById() that findNavController() depends on is going to fail since you never have a content view. Commented Jan 26, 2021 at 23:04
  • Thanks ianhanniballake for your further answer. Unfortunately your suggested code can't be built as I get the error message "Type parameter T has incompatible upper bounds: ViewDataBinding and ActivityMainBinding"
    – VanessaF
    Commented Jan 27, 2021 at 21:38
  • I searched for this error and I tried every option mentioned in this post: stackoverflow.com/questions/34368329/…. 1. Rename the XML file of the main activity. 2 Clean and Rebuild the project 3.Invalidate cache and restart. None of them had any effect. The error when using your suggested code still persists.
    – VanessaF
    Commented Jan 27, 2021 at 21:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.