HavanaSun
HavanaSun

Reputation: 936

How to change fragment with the Bottom Navigation Activity?

I created a new project with the "Bottom Navigation Activity":

enter image description here

This is the generated code:

package com.aaron.waller.mrpolitik;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView mTextMessage;

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

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    mTextMessage.setText(R.string.title_home);
                case R.id.navigation_dashboard:
                    mTextMessage.setText(R.string.title_dashboard);
                case R.id.navigation_notifications:
                    mTextMessage.setText(R.string.title_notifications);
            }
            return true;
        }

    };

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

        mTextMessage = (TextView) findViewById(R.id.message);
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
    }

}

How can I change to new Fragments with the Bottom Bar? For example I have 3 Fragments: Fragment1 Fragment2 and Fragment3 And I want to change to them with the 3 buttons from the Bottom Bar. Also I want that I can switch the Fragments by swiping my finger left and right how can I do that?

Upvotes: 27

Views: 72836

Answers (9)

Arezou_ghorbani
Arezou_ghorbani

Reputation: 19

Its my suggest way and it has an ideal performance I did it with using naveController and androidx.navigation:navigation

Step 1: Add the navigation dependency to your app-level build.gradle file. This will allow you to use the Navigation component in your app.

dependencies {
def nav_version = "2.3.5"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}

Step 2: Create a new menu resource file for the bottom navigation bar. This file will contain the menu items that will be displayed in the bar. To create a new menu resource file, right-click on the res folder in the Project panel, select New > Android resource file, and set the Resource type to Menu.

Step 3: In the menu resource file, add the menu items that will be displayed in the bottom navigation bar. Each menu item should have a unique ID and a title. For example:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:id="@+id/navigation_home"
    android:title="Home" />
<item
    android:id="@+id/navigation_dashboard"
    android:title="Dashboard" />
<item
    android:id="@+id/navigation_notifications"
    android:title="Notifications" />

Step 4: In the layout file where you want to display the bottom navigation bar, add a BottomNavigationView element. For example:

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

Note that the app:menu attribute is set to the name of the menu resource file created in step 2.

Step 5: In your activity or fragment that will host the bottom navigation bar, create an instance of NavController using the findNavController() method and pass in the BottomNavigationView as the argument. For example:

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

<fragment
    android:id="@+id/navigation_home"
    android:name="com.example.myapp.HomeFragment"
    android:label="@string/title_home" />

<fragment
    android:id="@+id/navigation_dashboard"
    android:name="com.example.myapp.DashboardFragment"
    android:label="@string/title_dashboard" />

<fragment
    android:id="@+id/navigation_notifications"
    android:name="com.example.myapp.NotificationsFragment"
    android:label="@string/title_notifications" />

Note that each fragment is identified by a unique ID, which corresponds to the ID of the menu item in the bottom navigation bar.

That's it! With these steps, you should now have a basic bottom navigation bar that can be used to replace different fragments in your app.

Upvotes: 1

Gantrol
Gantrol

Reputation: 351

There is another way to avoid recreating fragment -- fm.beginTransaction().hide(active).show(aimFragment)

My example is follow(just copy from my project recent):

public class MainActivity extends AppCompatActivity {
    @BindView(R.id.main_bottom_navigation) BottomNavigationView mBottomNavigationView;
    final Fragment mTaskListFragment = new TaskListFragment();
    final Fragment mUserGroupFragment = new UserGroupFragment();
    final Fragment mUserMeFragment = new UserMeFragment();
    final FragmentManager fm = getSupportFragmentManager();
    Fragment active = mTaskListFragment;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        mBottomNavigationView
                .setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
        fm.beginTransaction().add(R.id.main_fragment_container, mUserMeFragment, "3")
                .hide(mUserMeFragment).commit();
        fm.beginTransaction().add(R.id.main_fragment_container, mUserGroupFragment, "2")
                .hide(mUserGroupFragment).commit();
        fm.beginTransaction().add(R.id.main_fragment_container, mTaskListFragment, "1").commit();

    }


    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
        = item -> {
//        TODO: 这种切换方式比较快,但横竖屏切换会出问题,已经
            switch (item.getItemId()) {
                case R.id.nav_list:
                    fm.beginTransaction().hide(active).show(mTaskListFragment).commit();
                    active = mTaskListFragment;
                    break;
                case R.id.nav_group:
                    fm.beginTransaction().hide(active).show(mUserGroupFragment).commit();
                    active = mUserGroupFragment;
                    break;
                case R.id.nav_me:
                    fm.beginTransaction().hide(active).show(mUserMeFragment).commit();
                    active = mUserMeFragment;
                    break;
            }
            return true;
        };
}

It seems efficient and will work well until you rotate your phone. And I fixed it by adding the code following in the manifest file to the activity to retain the fragment state. (e.g. at AndroidManifest.xml):

android:configChanges="screenSize|orientation|screenLayout"

Upvotes: 1

Bibin Jaimon
Bibin Jaimon

Reputation: 592

You can switch fragments through below code if you are using Jetpack Navigation.

val navController = findNavController(R.id.your_nav_host_fragment)
navController.navigate(R.id.your_fragment_id_in_menu)

For more information go through this doc : https://codelabs.developers.google.com/codelabs/android-navigation/#0

Upvotes: 7

timothyjc
timothyjc

Reputation: 2228

The easy way is with the Navigation Component:

 bottom_navigation_view?.setupWithNavController(navController)

Upvotes: 2

Abdel Rahman
Abdel Rahman

Reputation: 254

The way I would do it is, I would first add three methods similar to this one (each for a single fragment. Replace the layout name and the fragment object to the appropriate fragment that is being switched to):

public void switchToFragment1() {
    FragmentManager manager = getSupportFragmentManager();
    manager.beginTransaction().replace(R.id.your_fragment_layout_name, new Fragment1()).commit();
}

So your switch statement would end up looking like this:

        switch (item.getItemId()) {
            case R.id.navigation_home:
                mTextMessage.setText(R.string.title_home);
                switchToFragment1();
                break;

            case R.id.navigation_dashboard:
                mTextMessage.setText(R.string.title_dashboard);                    
                switchToFragment2();
                break;

            case R.id.navigation_notifications:
                mTextMessage.setText(R.string.title_notifications);                     
                switchToFragment3();
                break;
        }

As for switching the fragments by swiping to the sides, I believe you would need a ViewPager.

Upvotes: 24

Vivek Shah
Vivek Shah

Reputation: 380

//fully tested  
  public class DashBoardActivity extends AppCompatActivity {

        Fragment fragment = null;
        FragmentTransaction fragmentTransaction;

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

            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.navigation_home:
                        return true;
                    case R.id.navigation_dashboard:
                        fragment = new FragmentDashBoard();
                        switchFragment(fragment);
                        return true;
                    case R.id.navigation_notifications:
                        fragment = new FragmentNotification();
                        switchFragment(fragment);
                        return true;
                }
                return false;
            }
        };


        private void switchFragment(Fragment fragment) {
            fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.content, fragment);
            fragmentTransaction.commit();
        }

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

            BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
            navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
            navigation.setSelectedItemId(R.id.navigation_dashboard);
        }

    }

Upvotes: 2

Abed Almoradi
Abed Almoradi

Reputation: 131

The best way is to use a ViewPager with a FragmentPagerAdapter. Since it cashes the fragments inside it. Use setOnNavigationItemSelectedListener with the BottomNavigationView to listen for the user's clicks. And use viewPager.setCurrentItem(..) to move between pages.

Creating a new fragment everytime the user clicks on an item in the bottom navigation view isn't a good solution (especially when the user clicks on the item of the screen that he is currently at, the solution above will create a new fragment even for this case)

Upvotes: 9

Ojonugwa Jude Ochalifu
Ojonugwa Jude Ochalifu

Reputation: 27237

It's pretty "simple".

  1. Create your Fragments. Let's say we want 3 fragments; FragmentA, FragmentB and FragmentC with FragmentA being the first Fragment we want on the BottomNavigationView.
  2. In your Activity, go to the onNavigationItemSelected method and change the content to this:

     private BottomNavigationView.OnNavigationItemSelectedListener  
       mOnNavigationItemSelectedListener
           = new BottomNavigationView.OnNavigationItemSelectedListener(){
    
       @Override
       public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    
        switch (item.getItemId()) {
            case R.id.frag_a:
                currentFragment = new FragmentA();
                ft = getSupportFragmentManager().beginTransaction();
                ft.replace(R.id.content, currentFragment);
                ft.commit();
                return true;
            case R.id.frag_b:
                currentFragment = new FragmentB();
                ft = getSupportFragmentManager().beginTransaction();
                ft.replace(R.id.content, currentFragment);
                ft.commit();
                return true;
            case R.id.frag_c:
                currentFragment = new FragmentC();
                ft = getSupportFragmentManager().beginTransaction();
                ft.replace(R.id.content, currentFragment);
                ft.commit();
                return true;
        }
    
        return false;
     }
    
    };
    
  3. In your onCreate()method, do this:

      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client_profile);
        ft = getSupportFragmentManager().beginTransaction();
        currentFragment = new FragmentA();
        ft.replace(R.id.content, currentFragment);
        ft.commit();
    
        BottomNavigationView navigation = (BottomNavigationView)  
        findViewById(R.id.navigation); navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
      }
    

If you do not add FragmentA in the onCreate(), the activity is blank when you first launch it.

If you are wondering what R.id.content refers to, it is the Id of the Framelayout in your activity's layout. It initially contains a TextView, delete the TextView so it looks like this:

<FrameLayout
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"/>

Finally, ft and currentFragment are defined like this:

Fragment currentFragment = null;
FragmentTransaction ft;

Not sure about elegance, but this works.

Upvotes: 11

Iqbal Suzetta
Iqbal Suzetta

Reputation: 1

you can use this one

                    fragmentManager = getFragmentManager();
                    transaction = fragmentManager.beginTransaction();

                    FragmentA a = new FragmentA();
                    transaction.replace(R.id.frame, a);
                    transaction.commit();

Upvotes: -2

Related Questions