0

I have an app and I would like to use the one activity multiple fragments approach. So for this I implemented a main activity class that should serve as a container for the fragments. Here you see the XML layout file of it (called activity_main2):

<?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">


    <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"
        />

    <fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph"
        tools:layout_editor_absoluteX="1dp"
        tools:layout_editor_absoluteY="1dp"
         />
</androidx.constraintlayout.widget.ConstraintLayout>

ANd here you see the Java file of it:

package com.example.td.barapp;

import android.content.Intent;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.os.Bundle;

import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import com.example.td.barapp.databinding.ActivityMain2Binding;
import com.example.td.barapp.databinding.ActivityMainBinding;


public class MainActivity extends AppCompatActivity  {


    private ActivityMain2Binding binding;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding=ActivityMain2Binding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());



    }

}

Unfortnunately when I start the app the app is not started and in the logcat I get the following error messag stack:

2020-08-26 17:07:47.202 16384-16384/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.td.barapp, PID: 16384
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.td.barapp/com.example.td.barapp.MainActivity}: android.view.InflateException: Binary XML file line #25 in com.example.td.barapp:layout/activity_main2: Binary XML file line #25 in com.example.td.barapp:layout/activity_main2: Error inflating class fragment
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: android.view.InflateException: Binary XML file line #25 in com.example.td.barapp:layout/activity_main2: Binary XML file line #25 in com.example.td.barapp:layout/activity_main2: Error inflating class fragment
     Caused by: android.view.InflateException: Binary XML file line #25 in com.example.td.barapp:layout/activity_main2: Error inflating class fragment
     Caused by: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.example.td.barapp.Menu_Fragment: could not find Fragment constructor
        at androidx.fragment.app.Fragment.instantiate(Fragment.java:563)
        at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57)
        at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:390)
        at androidx.navigation.fragment.FragmentNavigator.instantiateFragment(FragmentNavigator.java:132)

So something is said to be wrong with the XML layout file for the activity_main2 that I posted above. I just can't figure out what the problem is altough having spent quite some time on it. Could you help me on that? I would really really appreciate your comments as I do not know how to proceed. I would be quite thankful for your help.

Update: Here are the additional files that Dev (see below) asked me to post: Here is the java file for the menu_fragment:

package com.example.td.barapp;

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.NavDirections;
import androidx.navigation.Navigation;

import com.example.td.barapp.databinding.FragmentMenuBinding;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link Menu_Fragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class Menu_Fragment extends Fragment implements View.OnClickListener {

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;



    private Menu_Fragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment Menu_Fragment.
     */
    // TODO: Rename and change types and number of parameters
    public static Menu_Fragment newInstance(String param1, String param2) {
        Menu_Fragment fragment = new Menu_Fragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }


    }

    private FragmentMenuBinding binding;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        binding = FragmentMenuBinding.inflate(inflater, container, false);
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        binding.imageButtonCocktailsEn.setOnClickListener(this);
        binding.imageButtonCocktailsAlcfreeEn.setOnClickListener(this);
        binding.imageButtonLongdrinksEn.setOnClickListener(this);
        binding.imageButtonWhiskyEn.setOnClickListener(this);
        binding.imageButtonLiquorEn.setOnClickListener(this);
        binding.imageButtonBeerEn.setOnClickListener(this);
        binding.imageButtonSoftdrinksEn.setOnClickListener(this);
        binding.imageButtonHotDrinksEn.setOnClickListener(this);

    }

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


    @Override
    public void onClick(View view) {

        if(view.getId() == R.id.imageButton_Softdrinks_en) {

            int amount = 1;
            Menu_FragmentDirections.ActionMenuFragmentToSoftdrinks action = Menu_FragmentDirections
                    .actionMenuFragmentToSoftdrinks(amount);

            Navigation.findNavController(view).navigate(action);



        }

    }
}

And here the XML layout file for the menu fragment:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".Menu_Fragment">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar_mainActivity"
            android:layout_width="432dp"
            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/textView_ToolBar_CocktailSelectionActivity"
                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="Drinks" />
        </androidx.appcompat.widget.Toolbar>

        <ScrollView
            android:layout_width="0dp"
            android:layout_height="0dp"
            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_Cocktails_en"
                    android:layout_width="0dp"
                    android:layout_height="128dp"
                    android:layout_marginTop="12dp"
                    android:background="#00000000"
                    android:scaleType="fitCenter"
                    app:layout_constraintEnd_toStartOf="@id/imageButton_Cocktails_alcfree_en"
                    app:layout_constraintHorizontal_chainStyle="spread"
                    app:layout_constraintHorizontal_weight="1"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    app:srcCompat="@drawable/menu_cocktails" />

                <ImageButton
                    android:id="@+id/imageButton_Cocktails_alcfree_en"
                    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_Cocktails_en"
                    app:layout_constraintTop_toTopOf="parent"
                    app:srcCompat="@drawable/menu_cocktails_acoholfree" />

                <ImageButton
                    android:id="@+id/imageButton_Longdrinks_en"
                    android:layout_width="0dp"
                    android:layout_height="128dp"
                    android:layout_marginTop="12dp"
                    android:background="#00000000"
                    android:scaleType="fitCenter"
                    app:layout_constraintEnd_toStartOf="@id/imageButton_Whisky_en"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@id/imageButton_Cocktails_en"
                    app:layout_constraintVertical_chainStyle="packed"
                    app:srcCompat="@drawable/menu_longdrinks" />

                <ImageButton
                    android:id="@+id/imageButton_Whisky_en"
                    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_constraintStart_toEndOf="@id/imageButton_Longdrinks_en"
                    app:layout_constraintTop_toBottomOf="@id/imageButton_Cocktails_en"
                    app:srcCompat="@drawable/menu_whisky" />

                <ImageButton
                    android:id="@+id/imageButton_Liquor_en"
                    android:layout_width="0dp"
                    android:layout_height="128dp"
                    android:layout_marginTop="12dp"
                    android:background="#00000000"
                    android:scaleType="fitCenter"
                    app:layout_constraintEnd_toStartOf="@id/imageButton_Beer_en"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@id/imageButton_Longdrinks_en"
                    app:layout_constraintVertical_chainStyle="packed"
                    app:srcCompat="@drawable/menu_liquor" />

                <ImageButton
                    android:id="@+id/imageButton_Beer_en"
                    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_constraintStart_toEndOf="@id/imageButton_Liquor_en"
                    app:layout_constraintTop_toBottomOf="@id/imageButton_Longdrinks_en"
                    app:srcCompat="@drawable/menu_beer" />


                <ImageButton
                    android:id="@+id/imageButton_Softdrinks_en"
                    android:layout_width="0dp"
                    android:layout_height="128dp"
                    android:layout_marginTop="12dp"
                    android:background="#00000000"
                    android:scaleType="fitCenter"
                    app:layout_constraintEnd_toStartOf="@id/imageButton_HotDrinks_en"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@id/imageButton_Liquor_en"
                    app:layout_constraintVertical_chainStyle="packed"
                    app:srcCompat="@drawable/menu_softdrinks" />

                <ImageButton
                    android:id="@+id/imageButton_HotDrinks_en"
                    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_constraintStart_toEndOf="@id/imageButton_Softdrinks_en"
                    app:layout_constraintTop_toBottomOf="@id/imageButton_Liquor_en"
                    app:srcCompat="@drawable/menu_hot_drinks" />


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


        <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>

</FrameLayout>
VanessaF
  • 515
  • 11
  • 36

1 Answers1

1

First of all, change the <fragment tag in you activity_main2.xml file to a FrameLayout because using a FrameLayout is necessary for switching between Fragments. Then use this code in your MainActivity java class:

public class MainActivity extends AppCompatActivity  {

   //This will be used to switch between Fragments
   private static FragmentManager fragmentManager;
   private BottomNavigationView bottomNavView;
    

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

        //Initialize the FragmentManager
        fragmentManager = getSupportFragmentManager();

        //Initialize the BottomNavigationView and add listener to it
        bottomNavView = findViewById(R.id.bottom_navigation);
        bottomNavView.setOnNavigationItemSelectedListener(bottomNavListener);     
    }

    private BottomNavigationView.OnNavigationItemSelectedListener bottomNavListener = 
new BottomNavigationView.OnNavigationItemSelectedListener(){

       @Override
       public boolean OnNavigationItemSelected(@NonNull MenuItem item){
       
           Fragment selectedFragment = null;

           switch(item.getItemId()){

                 case R.id.{first fragment}:
                     selectedFragment = new {first fragment}();
                     break;

                 case R.id.{second fragment}:
                     selectedFragment = new {second fragment}();
                     break;
                 
                  .
                  .
                  .

                 {Make a case for each of your fragments}
           }

           fragmentManager.beginTransaction().replace(R.id.{id of your FrameLayout}, selectedFragment).commit();

       }
     }; 
}

This should work now.

Dev Randalpura
  • 126
  • 1
  • 4
  • Thanks Dev for your answer. I added your code. Now I get a new error: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference at androidx.fragment.app.FragmentTransaction.doAddOp(FragmentTransaction.java:161) at androidx.fragment.app.BackStackRecord.doAddOp(BackStackRecord.java:179) at androidx.fragment.app.FragmentTransaction.replace(FragmentTransaction.java:225) at androidx.fragment.app.FragmentTransaction.replace(FragmentTransaction.java:200) – VanessaF Aug 26 '20 at 16:05
  • at com.example.td.barapp.Selection_Softdrinks_Activity$1.onNavigationItemSelected(Selection_Softdrinks_Activity.java:49) at com.google.android.material.bottomnavigation.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:243) at androidx.appcompat.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:840) at androidx.appcompat.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:158) at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:991) – VanessaF Aug 26 '20 at 16:06
  • at com.google.android.material.bottomnavigation.BottomNavigationMenuView$1.onClick(BottomNavigationMenuView.java:127) – VanessaF Aug 26 '20 at 16:06
  • So I have a BottomNavigationBar (as can be seen in the layout file) and somehow there is an error in it. But basically I could use the BottomNavigatonBar before so I do not know where the error is – VanessaF Aug 26 '20 at 16:07
  • I have already posted the XML layout file and the Java file. You can see them above – VanessaF Aug 26 '20 at 16:08
  • When I remove the method mentioned in the second error (after having applied your changes) the first error occurs again. "android.view.InflateException: Binary XML file line #25 in com.example.td.barapp:layout/activity_main2: Binary XML file line #25 in com.example.td.barapp:layout/activity_main2: Error inflating class fragment" – VanessaF Aug 26 '20 at 16:51
  • Can you tell me what is in line 49 of Selection_Softdrinks_Activity.java? Also, by the files, I meant the layout and Java files for the fragment which is in the Main Activity. – Dev Randalpura Aug 26 '20 at 17:04
  • Basically I commented the line 49 of Selection_Softdrinks_Activity.java out and the problem still exists (the line was "if (selectedFragment!=null)") – VanessaF Aug 26 '20 at 17:08
  • Do you want to try another approach of using a FragmentTransaction? For that I'll need to know what is in your Fragment java and layout files so you should send them. – Dev Randalpura Aug 26 '20 at 17:13
  • Hi Dev, thanks a lot for your answers and effort. I uploaded the two files you wanted. Maybe they can help you finding out what goes wrong. – VanessaF Aug 26 '20 at 17:18
  • In the Fragment's onCreateView, replace `binding = FragmentMenuBinding.inflate(inflater, container, false); return binding.getRoot();` with `return inflater.inflate(R.layout.{name of your layout file}, container, false);`. Also, you haven't initialized any of your ImageButtons in the Fragment class. – Dev Randalpura Aug 26 '20 at 17:27
  • Thanks for the comment Dev. I did what you said (without initializing the ImageButtoms as there is no need for that because I am using ViewBinding). The problem still persists without any changes. I get the same error message – VanessaF Aug 26 '20 at 18:02
  • By the way I was told yesterday in this thread (https://stackoverflow.com/questions/63581206/problem-with-viewbindng-in-fragments-in-android) to do the opposite of what you told be to do regarding the ViewBinding – VanessaF Aug 26 '20 at 18:04
  • Since you mentioned the BottomNavigationView, I'm thinking it might have something to do with the problem. Are you thinking of switching the fragments based on the item selected in the NavigationView? – Dev Randalpura Aug 26 '20 at 18:31
  • Thanks Dev for your answer and effort. Yes basically the BottomNavigationView is intended to be used for switching the fragments. Just one interesting observation that I made: When choosing another Fragment as the Home Fragment (that should be initally loaded) in the Nav_Graph, the app starts and I do not get this error. The striking point is, that the other Fragment is quite similar to the 'erroneous' activity_main2 fragment (it also has the same BottomNavigationView). – VanessaF Aug 26 '20 at 20:18
  • Unfortunately I can't upload the other Fragment that works well due to size restrictions by Stackexchange – VanessaF Aug 26 '20 at 20:22
  • Let us continue this discussion in chat. – VanessaF Aug 26 '20 at 20:32
  • Somehow the chat function does not work in this post (as opposed to every other post I have experienced in StackExchange). So I can't post the other class and XML file of the fragment that works if choosen as the HomeFragment in the Nav_Graph. But as said before, it is quite similar to the other one. – VanessaF Aug 26 '20 at 20:35
  • I think the problem is this: in your Main Activity xml file, you have a ``. However it can't be used if you want to switch between fragments. I'm editing this answer because I can't type everything in a comment. – Dev Randalpura Aug 26 '20 at 22:11
  • Thanks Dev for your comment. But I want to use the Jetpack Navigation components and here I have to use the fragment or the FragmentContainerView tag (see https://developer.android.com/guide/navigation/navigation-getting-started). Further, this can not be the reason as when choosing another home destination that is displayed within the activty_main2.xml layout it works without problems. So I would infer that the error is not in the activity_main2.xml file (and not in the Java file). I guess it is in the menu fragment XML or Java file (that I had also posted as an update) – VanessaF Aug 27 '20 at 07:34
  • Okay I found the error. The constructor of Menu_Fragment was private (because of StackExchange someone yesterday told me to do it private). That is not correct. It should be public. – VanessaF Aug 27 '20 at 08:07
  • Ok, glad you found the error and glad I could help. – Dev Randalpura Aug 27 '20 at 14:35