简体   繁体   中英

How to change fragment with the Bottom Navigation Activity?

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

在此处输入图片说明

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?

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 .

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.

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)

//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);
        }

    }

简单的方法是使用导航组件:

 bottom_navigation_view?.setupWithNavController(navController)

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

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. (eg at AndroidManifest.xml ):

android:configChanges="screenSize|orientation|screenLayout"

you can use this one

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM