Tony Starkus
Tony Starkus

Reputation: 576

Switch between Fragments in BottomNavigationView

I'm working with a simple app with Bottom Navigation View. I have 3 fragments (layout and java). I have BottonNavigationView, declared in my MainActivity.java. My bottonnavigation have 3 items, for the 3 fragments. So, in my MainActivity.java, when i select a item, it start one fragment. So, when i select again another item, nothing happens, because in the java fragment i need to declare the BottonNavigationView, but i don't know how to set it to switch the actual fragment with another fragment. I tried this link, but no success: https://developer.android.com/training/basics/fragments/fragment-ui.html

Sorry my bad english

Here the codes:

Main Activity

 @Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    Fragment selectedFragment = null;
    switch (item.getItemId()) {
        case R.id.navigation_home:
            selectedFragment = HomeFragment.newInstance();
            break;
        case R.id.navigation_dashboard:
            selectedFragment = DashboardFragment.newInstance();
            break;
        case R.id.navigation_notifications:
            selectedFragment = NotificationsFragment.newInstance();
            break;
    }
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.content, selectedFragment);
    transaction.commit();
    return true;
}

Fragment Java Example

public class HomeFragment extends Fragment {
public static HomeFragment newInstance() {
HomeFragment fragment = new HomeFragment();
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.navigation_home, container, false);
return inflater.inflate(R.layout.navigation_home, container, false);
}

Upvotes: 5

Views: 16897

Answers (6)

Apelsinovich
Apelsinovich

Reputation: 1

My full solution, I think will be usefull for juniors:

So, we have MainActivity:

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

class MainMenuActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)

  val bottomNav: BottomNavigationView = findViewById(R.id.bottom_naviagtion)
  bottomNav.setOnNavigationItemSelectedListener(navListener)

    if (savedInstanceState == null) {
         supportFragmentManager.beginTransaction().replace(
              R.id.fragment_container,
             HomeFragment()
         ).commit()
     }
 }

 private val navListener: BottomNavigationView.OnNavigationItemSelectedListener =
      BottomNavigationView.OnNavigationItemSelectedListener { item ->
         var selectedFragment: Fragment? = null
         when (item.itemId) {
        R.id.bottom_home -> selectedFragment =
            HomeFragment()
        R.id.bottom_events -> selectedFragment =
            EventFragment()
        R.id.bottom_contacts -> selectedFragment =
            ContactsFragment()
        R.id.bottom_menu -> selectedFragment =
            MenuFragment()
    }
    supportFragmentManager.beginTransaction().replace(
        R.id.fragment_container,
        selectedFragment!!
     ).commit()
     true
 }
}

activity_main.xml:

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

<FrameLayout
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@id/bottom_naviagtion"/>

<View
    android:layout_width="match_parent"
    android:layout_height="10dp"
    android:layout_above="@id/bottom_naviagtion"
    android:background="@drawable/shadow"/>

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottom_naviagtion"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    app:menu="@menu/bottom_menu"
    android:background="?android:attr/windowBackground" />

</RelativeLayout>

Each fragment class looks like:

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

class HomeFragment : Fragment() {
   override fun onCreateView(
       inflater: LayoutInflater,
       container: ViewGroup?,
       savedInstanceState: Bundle?
   ): View? {
       return inflater.inflate(R.layout.fragment_home, container, false)
   }
 }

.xml file for HomeFragment (fragment_home.xml) looks like (other fragments looks the same):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/home"
    android:textSize="30sp"
    android:layout_centerInParent="true"/>

</RelativeLayout>

NavigationBottomMenu .xml looks (bottom_menu.xml):

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

<item
    android:id="@+id/bottom_home"
    android:icon="@drawable/home_selector"
    android:title="Home" />


<item
    android:id="@+id/bottom_events"
    android:icon="@drawable/events_selector"
    android:title="Events" />

<item
    android:id="@+id/bottom_contacts"
    android:icon="@drawable/contacts_selector"
    android:title="Contacts"/>

<item
    android:id="@+id/bottom_menu"
    android:icon="@drawable/menu_selector"
    android:title="Menu" />

</menu>

Used icons from drawble folder were imported like Vector Asset

Upvotes: 0

100rbh
100rbh

Reputation: 763

Just to add a blank implementation like this in onCreate bottomNavView.setOnNavigationItemReselectedListener {}

Upvotes: 0

Thien Huynh
Thien Huynh

Reputation: 166

You can try it:

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    Fragment selectedFragment = null;
    switch (item.getItemId()) {
        case R.id.navigation_home:
            selectedFragment = HomeFragment.newInstance();
            break;
        case R.id.navigation_dashboard:
            selectedFragment = DashboardFragment.newInstance();
            break;
        case R.id.navigation_notifications:
            selectedFragment = NotificationsFragment.newInstance();
            break;
    }
    getSupportFragmentManager().beginTransaction().replace(R.id.content, selectedFragment).commit();
    return true;
}

Upvotes: 9

Arman Hosseini
Arman Hosseini

Reputation: 63

You should create once newIstance from each your Fragments. and later you can hide active fragment and then show new fragment.

    Fragment activeFragment;
    ArrayList<Fragment> fragment;

public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            Fragment selectedFragment = null;
            switch (item.getItemId()) {
                case R.id.navigation_fragment:
                    selectedFragment = ShowMyFragment.newInstance();
                    replaceFragment(selectedFragment);
                    return true;
}
});
    private void replaceFragment(Fragment selectedFragment) {
        boolean lastOpened = false;
        for ( int i=0; i<fragment.size();i++ )
        {
            if ( fragment.get(i) == selectedFragment ) {
                lastOpened = true;
                break;
            }
        }
        if (!lastOpened) {
            getSupportFragmentManager().beginTransaction().replace(R.id.content, selectedFragment).commit();
        }
        else
        {
            getSupportFragmentManager().beginTransaction().hide(activeFragment).show(selectedFragment).commit();
        }

        activeFragment = selectedFragment;
    }

Upvotes: 0

rajeswari ratala
rajeswari ratala

Reputation: 710

You don't have to create newInstance every time. you can save the fragment states. follow the below link

fragmentManager.beginTransaction().hide(toBeHidden).show(toBeShown).commit();

https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711

Upvotes: 6

Djek-Grif
Djek-Grif

Reputation: 1516

In this case is better to try get exist fragment from fragmentManager like fragmentManager.findFragmentByTag(tag). You can switch more smoothly and you don't need for example load some content from network (if you have such code in fragment or presenter of fragment)

Upvotes: 2

Related Questions