Search code examples
androidbottomnavigationview

Android Studio: BottomNavigationView and transaction between fragments


I am trying to implement BottomNavigationView from Jetpack

def nav_version = "2.0.0"
// Java language implementation
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"

First test was done excluding the commented lines presented below and the transactions were done automatically by the library.

This way, the problem I faced was: if I press 100 times the bottom menu, I need to press 100 times the back button to do all the way back to MainFragment.

Second test was done uncommenting the commented lines and the transactions were hardcoded.

This way, the problem I faced was: The Fragment content overlapped one another and I could not figure out what I was doing wrong.

Because of an unsuccessful second test, I run the app without the commented lines (I deleted it) presented below once again, but the automatic transaction by the library (experienced in the first test) is not working anymore. I mean only the MainFragment is been launched, the others are not.

public class MainActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {

    private static final String TAG = "debinf MainActivity";

    //public static final String FRAGMENT_KEY = "fragment";

    private BottomNavigationView bottomNavigationView;
    private NavigationView navigationView;
    private DrawerLayout drawerLayout;
    private NavController navController;

    private AppBarConfiguration appBarConfiguration;

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

        Log.i(TAG, "onCreate: ");

        bottomNavigationView = (BottomNavigationView) findViewById(R.id.main_bottomnav);
        navigationView = (NavigationView) findViewById(R.id.main_sidebar);
        drawerLayout = (DrawerLayout) findViewById(R.id.main_drawer);

        setupNavigation();

        // Fragment been created for the first time
        /*if (getSupportFragmentManager().findFragmentByTag(FRAGMENT_KEY) == null) {
            Log.i(TAG, "onCreate: First fragment been created: MainFragment()");
            fragmentTransaction(new MainFragment());
        }*/

    }

    private void setupNavigation() {
        Log.i(TAG, "setupNavigation: ");
        navController = Navigation.findNavController(this, R.id.main_fragment);

        appBarConfiguration =
                new AppBarConfiguration.Builder(navController.getGraph())
                        .setDrawerLayout(drawerLayout)
                        .build();

        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(navigationView, navController);
        NavigationUI.setupWithNavController(bottomNavigationView, navController);
        // Listener for bottomNavigation must be called after been setupWithNavController
        bottomNavigationView.setOnNavigationItemSelectedListener(this);
    }

    /*private void fragmentTransaction(Fragment fragment) {
        Log.i(TAG, "fragmentTransaction: Hardcoded Transaction");
        getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

        getSupportFragmentManager()
                .beginTransaction()
                .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
                .replace(R.id.main_fragment, fragment, null)
                .commit();
    }*/



    @Override
    public void onBackPressed() {
        Log.i(TAG, "onBackPressed: ");
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }

    }

    @Override
    public boolean onSupportNavigateUp() {
        Log.i(TAG, "onSupportNavigateUp: ");
        return NavigationUI.navigateUp(navController, appBarConfiguration);
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        Log.i(TAG, "onNavigationItemSelected: ");

        if (menuItem.getItemId() == R.id.mainFragment) {
            Log.i(TAG, "onNavigationItemSelected: mainFrag");
            //fragmentTransaction(new MainFragment()); // Hardcoded transaction
        }
        if (menuItem.getItemId() == R.id.shopFragment) {
            Log.i(TAG, "onNavigationItemSelected: shopFrag");
            //fragmentTransaction(new ShopFragment()); // Hardcoded transaction
        }
        if (menuItem.getItemId() == R.id.searchFragment) {
            Log.i(TAG, "onNavigationItemSelected: searchFragment");
            //fragmentTransaction(new SearchFragment()); // Hardcoded transaction
        }
        return true;
    }

}

What do I have to do to have the automatic transaction by the Jetpack library back?

P.S.: I have not changed a bit of code anywhere else besides what is shown in the code above.

EDIT

Below is nav_graph.xml I would like to press back button one time to go back to MainFragment and press back button again to leave the app (first test problem).

I appreciate any help!

<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/mainnav_graph"
    app:startDestination="@id/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.aelecomerce.goodstag.MainFragment"
        android:label="fragment_main"
        tools:layout="@layout/fragment_main" />

    <fragment
        android:id="@+id/shopFragment"
        android:name="com.aelecomerce.goodstag.ShopFragment"
        android:label="fragment_shop"
        tools:layout="@layout/fragment_shop" >

        <action
            android:id="@+id/openAddstoreFragment"
            app:destination="@id/addstoreFragment"
            app:enterAnim="@anim/nav_default_enter_anim"/>
        <action
            android:id="@+id/openBarcodeFragment"
            app:destination="@id/barcodeFragment" />
    </fragment>

    <fragment
        android:id="@+id/searchFragment"
        android:name="com.aelecomerce.goodstag.SearchFragment"
        android:label="fragment_search"
        tools:layout="@layout/fragment_search" />

    <fragment
        android:id="@+id/addstoreFragment"
        android:name="com.aelecomerce.goodstag.AddstoreFragment"
        android:label="fragment_addstore"
        tools:layout="@layout/fragment_addstore" />
    <fragment
        android:id="@+id/barcodeFragment"
        android:name="com.aelecomerce.goodstag.BarcodeFragment"
        android:label="fragment_barcode"
        tools:layout="@layout/fragment_barcode" />
</navigation>

Below is the menu for the BottomNavigationView

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@id/mainFragment"
        android:title="Home"
        android:icon="@android:drawable/stat_sys_phone_call_on_hold"
        android:menuCategory="secondary"/>

    <item
        android:id="@id/shopFragment"
        android:title="Shop"
        android:icon="@android:drawable/stat_sys_phone_call_on_hold"
        android:menuCategory="secondary"/>

    <item
        android:id="@id/searchFragment"
        android:title="Search"
        android:icon="@android:drawable/stat_sys_phone_call_on_hold"
        android:menuCategory="secondary"/>

</menu>

And below is the main_activity.xml

<androidx.drawerlayout.widget.DrawerLayout
    android:id="@+id/main_drawer"
    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">


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

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

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/main_bottomnav"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/main_navmenu"
            android:background="@color/colorAccent"
            app:itemIconTint="@drawable/botton_item_color"
            app:itemTextColor="@drawable/botton_item_color">

        </com.google.android.material.bottomnavigation.BottomNavigationView>

    </androidx.constraintlayout.widget.ConstraintLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/main_sidebar"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/main_sidebarmenu"/>

</androidx.drawerlayout.widget.DrawerLayout>

Solution

  • Remove the line

    bottomNavigationView.setOnNavigationItemSelectedListener(this);
    

    As that is overriding the OnNavigationItemSelectedListener set by setupWithNavController().