BottomNavigationView - 如何避免重新创建片段并重用它们

BottomNavigationView - How to avoid recreation of Fragments and reuse them

我想在我的项目中做一个底部导航栏。每个视图都有自己的片段。问题是,每次我点击按钮更改视图,例如从最近到收藏夹,它都会创建具有全新状态的新片段(例如,滚动位置,无论我的片段包含什么,文本都会改变)。我知道在官方 Android 文档中写到底部导航栏应该重置任务状态,但我认为这对用户来说太不舒服了。 我想拥有类似 instagram 的功能,您可以从提要更改为探索,然后返回到提要滚动位置图像缓存所有内容都保留下来。我几乎尝试了所有方法来解决这个问题,唯一有效的方法是根据情况设置可见性 GONE 和设置可见性 VISIBLE,但我知道这不是正确的方法,应该有更好的方法,我不是在谈论手动保存需要的实例。我几乎遵循了所有关于底部导航片段的教程,但有趣的是,没有人有兴趣在每次不调用 new 的情况下使用它。

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frameLayout, FirstFragment.newInstance());
fragmentTransaction.commit();

bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        Fragment fragment = null;
        switch (item.getItemId()) {
            case R.id.menu_dialer:
                fragment = FirstFragment.newInstance();
                break;
            case R.id.menu_email:
                fragment = SecondFragment.newInstance();
                break;
            case R.id.menu_map:
                fragment = ThirdFragment.newInstance();
                break;
        }
        if (fragment != null) {
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frameLayout, fragment);
            fragmentTransaction.commit();
        }
        return true;
    }
});

我也尝试了 onAttach 和 Deattach 解决方案,但还是没有成功。

VIDEO LINK : new i tried Nino Handler version it only works when i tap on the same fragment button

可能与我使用的金丝雀版本有关,或者我的 gradle 依赖项有问题?

新更新:

public class MainActivity extends AppCompatActivity {

    private TextView mTextMessage;


    private static final String TAG_FRAGMENT_ONE = "fragment_one";
    private static final String TAG_FRAGMENT_TWO = "fragment_two";

    private FragmentManager fragmentManager;
    private Fragment currentFragment;

    String TAG = "babken";
    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {

        Fragment fragment = null;
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                   fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);
                    if (fragment == null) {
                        fragment = FragmentFirst.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_ONE);

                    break;
                case R.id.navigation_dashboard:

                     fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_TWO);
                    if (fragment == null) {
                        fragment = FragmentSecond.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_TWO);

                    break;
            }
            return true;

        }
    };

    private void replaceFragment(@NonNull Fragment fragment, @NonNull String tag) {
        if (!fragment.equals(currentFragment)) {
            fragmentManager
                    .beginTransaction()
                    .replace(R.id.armen, fragment, tag)
                    .commit();
            currentFragment = fragment;
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentManager = getSupportFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);
        if (fragment == null) {
            fragment = FragmentFirst.newInstance();
        }
        replaceFragment(fragment, TAG_FRAGMENT_ONE);
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
    }

}

怎么样。 您在 class.

中声明片段
Fragment firstFragment,secondFragment,thirdFragment;

然后在 switch-case 你可以这样编码:

switch (item.getItemId()) {
    case R.id.menu_dialer:
        if(firstFragment != null) {
            fragment = firstFragment;
        }else{
            fragment = FirstFragment.newInstance();
        }
        break;
    case R.id.menu_email:
        // the same ...
        break;
    case R.id.menu_map:
        //the same ...
        break;
}

创建三个片段作为 class 的成员并重新使用它们。

public class MainActivity extends AppCompatActivity {
    private final Fragment mFirstFragment = new FirstFragment();
    private final Fragment mSecondFragment = new SecondFragment();
    private final Fragment mThirdFragment = new ThirdFragment();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...... 
        ......
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.frameLayout, mFirstFragment);
        fragmentTransaction.commit();

        bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                if (bottomNavigationView.getSelectedItemId() != item.getItemId()) {
                    switch (item.getItemId()) {
                        R.id.menu_dialer:
                            replaceFragment(mFirstFragment);
                            break;
                        case R.id.menu_email:
                            replaceFragment(mSecondFragment);
                            break;
                        case R.id.menu_map:
                            replaceFragment(mThirdFragment);
                            break;
                    }
                }
                return true;
            }
        });
    }

    private void replaceFragment(Fragment fragment) {
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.frameLayout, fragment);
        fragmentTransaction.commit();
    }

}

我不会全局保留片段实例。 而是在创建它们时向片段添加标签

getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.container, new PlaceholderFragment(), TAG_PLACEHOLDER)
            .commit();

然后你总是可以像这样检索它:

Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_PLACEHOLDER);
    if (fragment == null) {
        fragment = new PlaceholderFragment();
    }
    getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.container, fragment, TAG_PLACEHOLDER)
            .commit();

更新:我更新了我的答案并提供了一个完整的解决方案:

private static final String TAG_FRAGMENT_ONE = "fragment_one";
private static final String TAG_FRAGMENT_TWO = "fragment_two";
private static final String TAG_FRAGMENT_THREE = "fragment_three";

private FragmentManager fragmentManager;
private Fragment currentFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // instantiate the fragment manager
    fragmentManager = getSupportFragmentManager();

    Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);
    if (fragment == null) {
        fragment = FirstFragment.newInstance();
    }
    replaceFragment(fragment, TAG_FRAGMENT_ONE);

    bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
    bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            Fragment fragment = null;
            switch (item.getItemId()) {
                case R.id.menu_dialer:
                    // I'm aware that this code can be optimized by a method which accepts a class definition and returns the proper fragment
                    Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE);
                    if (fragment == null) {
                        fragment = FirstFragment.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_ONE);
                    break;
                case R.id.menu_email:
                    Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_TWO);
                    if (fragment == null) {
                        fragment = SecondFragment.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_TWO);
                    break;
                case R.id.menu_map:
                    Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_THREE);
                    if (fragment == null) {
                        fragment = ThirdFragment.newInstance();
                    }
                    replaceFragment(fragment, TAG_FRAGMENT_THREE);
                    break;
            }
            return true;
        }
    });
}

private void replaceFragment(@NonNull Fragment fragment, @NonNull String tag) {
    if (!fragment.equals(currentFragment)) {
        fragmentManager
            .beginTransaction()
            .replace(R.id.frameLayout, fragment, tag)
            .commit();
        currentFragment = fragment;
    }
}

附加信息:如果您想确保片段状态不会改变,并且如果您还希望能够滑动片段,您应该考虑使用 ViewPager with a FragmentStatePagerAdapter 并更改当前片段每次点击事件的适配器

所以我为此研究了很长时间,发现没有办法重用自动保存状态的片段,你必须手动保存你需要的状态,然后在创建新片段时检索它们,但是什么关于滚动位置它太难了,甚至在某些情况下无法保存滚动视图位置状态(例如回收视图)。因此,当我单击片段变得可见的按钮时,我使用了称为 VISIBILITY 的概念,其他片段会自动隐藏。

之前的回答都是用fragmentTransaction.replace(...)。这将通过销毁它来替换当前片段(这是导致问题的原因)。因此,所有这些解决方案实际上都行不通。

这是我能找到的最接近这个问题的解决方案:

private void selectContentFragment(Fragment fragmentToSelect)
{
    FragmentTransaction fragmentTransaction = this.getSupportFragmentManager().beginTransaction();

    if (this.getSupportFragmentManager().getFragments().contains(fragmentToSelect)) {
        // Iterate through all cached fragments.
        for (Fragment cachedFragment : this.getSupportFragmentManager().getFragments()) {
            if (cachedFragment != fragmentToSelect) {
                // Hide the fragments that are not the one being selected.
                fragmentTransaction.hide(cachedFragment);
            }
        }
        // Show the fragment that we want to be selected.
        fragmentTransaction.show(fragmentToSelect);
    } else {
        // The fragment to be selected does not (yet) exist in the fragment manager, add it.
        fragmentTransaction.add(R.id.fragment_container, fragmentToSelect);
    }

    fragmentTransaction.commit();
}

要完成这项工作,您应该在 Activity 中跟踪数组(或单独变量)中的片段。我参考 pre-instantiated SparseArray 中的所有片段。

我遇到了类似的问题,但这段代码解决了我的问题。

public class MainActivity extends AppCompatActivity {

    boolean doubleBackToExitPressedOnce = false;
    final Fragment fragment1 = new HomeFragment();
    final Fragment fragment2 = new DashboardFragment();
    final Fragment fragment3 = new NotificationsFragment();
    final FragmentManager fm = getSupportFragmentManager();
    Fragment active = fragment1;
    BottomNavigationView navigation;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
        setFragment(fragment1, "1", 0);
    }


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

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    setFragment(fragment1, "1", 0);
                    return true;
                case R.id.navigation_dashboard:
                    setFragment(fragment2, "2", 1);
                    return true;
                case R.id.navigation_notifications:
                    setFragment(fragment3, "3", 2);
                    return true;
            }
            return false;
        }
    };

    public void setFragment(Fragment fragment, String tag, int position) {
        if (fragment.isAdded()) {
            fm.beginTransaction().hide(active).show(fragment).commit();
        } else {
            fm.beginTransaction().add(R.id.main_container, fragment, tag).commit();
        }
        navigation.getMenu().getItem(position).setChecked(true);
        active = fragment;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_settings) {
            startActivity(new Intent(MainActivity.this, SettingsActivity.class));
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
        if (active == fragment1) {
            if (doubleBackToExitPressedOnce) {
                super.onBackPressed();
                return;
            }
            this.doubleBackToExitPressedOnce = true;
            Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
        } else {
            setFragment(fragment1, "1", 0);
        }
    }
}

您可以使用 attach() 和 detach() 方法:

private FirstFragment firstFragment = FirstFragment.newInstance();
private SecondFragment secondFragment= SecondFragment.newInstance();
private ThirdFragment thirdFragment = ThirdFragment.newInstance();

navigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.menu_dialer:
                    changeFragment(firstFragment, "firstFragment");
                    return true;
                case R.id.menu_email:
                    changeFragment(secondFragment, "secondFragment");
                    return true;
                case R.id.menu_map:
                    changeFragment(thirdFragment, "thirdFragment");
                    return true;
            }
            return false;
        }
    });

public void changeFragment(Fragment fragment, String tagFragmentName) {

    FragmentManager mFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

    Fragment currentFragment = mFragmentManager.getPrimaryNavigationFragment();
    if (currentFragment != null) {
        fragmentTransaction.detach(currentFragment);
    }

    Fragment fragmentTemp = mFragmentManager.findFragmentByTag(tagFragmentName);
    if (fragmentTemp == null) {
        fragmentTemp = fragment;
        fragmentTransaction.add(R.id.content, fragmentTemp, tagFragmentName);
    } else {
        fragmentTransaction.attach(fragmentTemp);
    }

    fragmentTransaction.setPrimaryNavigationFragment(fragmentTemp);
    fragmentTransaction.setReorderingAllowed(true);
    fragmentTransaction.commitNowAllowingStateLoss();
}

我为 FragmentManager 写了一个 Kotlin 扩展函数 class

fun FragmentManager.switch(containerId: Int, newFrag: Fragment, tag: String) {

    var current = findFragmentByTag(tag)
    beginTransaction()
        .apply {

            //Hide the current fragment
            primaryNavigationFragment?.let { hide(it) }

            //Check if current fragment exists in fragmentManager
            if (current == null) {
                current = newFrag
                add(containerId, current!!, tag)
            } else {
                show(current!!)
            }
        }
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        .setPrimaryNavigationFragment(current)
        .setReorderingAllowed(true)
        .commitNowAllowingStateLoss()
}

这可以由 supportFragmentManager.swtich(R.id.container,newFrag,newFrag.TAG)onNavigationItemSelected

调用

Thomas 的回答几乎帮助了我,但有一个问题,每当我第一次打开新片段时,它们会重叠,但一旦我按下菜单按钮再次打开它们就不会重叠。

于是我修改了他的代码,使用如下代码得到了解决方案:

 private fun selectContentFragment(fragmentToSelect: Fragment) {
        val fragmentTransaction = fragmentManager?.beginTransaction()
        if (fragmentManager?.fragments?.contains(fragmentToSelect)!!) {
            // Show the fragment that we want to be selected.
            fragmentTransaction?.show(fragmentToSelect)
        } else {
            // The fragment to be selected does not (yet) exist in the fragment manager, add it.
            fragmentTransaction?.add(R.id.container, fragmentToSelect)
        }
        // Iterate through all cached fragments.
        for (cachedFragment in fragmentManager?.fragments!!) {
            if (cachedFragment !== fragmentToSelect) {
                // Hide the fragments that are not the one being selected.
                // Uncomment following line and change the name of the fragment if your host isn't an activity and a fragment otherwise whole view will get hidden.
                // if (!cachedFragment.toString().contains("HomeContainerFragment"))

                fragmentTransaction?.hide(cachedFragment)
            }
        }
        fragmentTransaction?.commit()
    }

确保您不会每次都传递片段的新实例。

这行得通:

selectContentFragment(
                    when (item.itemId) {
                        R.id.home -> frag1
                        R.id.photoGallery -> frag2
                        else -> Home()
                    }
            )

其中 frag1frag2 是全局变量,定义为:

 val frag1 = Home()
 val frag2 = PhotoGallery()

这行不通:

selectContentFragment(
                    when (item.itemId) {
                        R.id.home -> Home()
                        R.id.photoGallery -> PhotoGallery()
                        else -> Home()
                    }
            )

浪费了我好几个小时。希望对大家有帮助!

**这段代码对我很有帮助。就像优酷一样。 **

private Deque<Integer> fragmentIds = new ArrayDeque<>(3);
int itemId;
private HomeFragment homeFragment = new HomeFragment();
private FavouriteFragment favouriteFragment = new FavouriteFragment();
private NearmeFragment nearmeFragment = new NearmeFragment();
BottomNavigationView bottomNavigationView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    fragmentIds.push(R.id.action_home);
    showTabWithoutAddingToBackStack(homeFragment);
    bottomNavigationView = findViewById(R.id.bottom_navigation);
    bottomNavigationView.setOnNavigationItemSelectedListener(onNavigationItemClicked);
}

private BottomNavigationView.OnNavigationItemSelectedListener onNavigationItemClicked = new BottomNavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        itemId= item.getItemId();
        if(fragmentIds.contains(itemId)){
            fragmentIds.remove(itemId);
        }
        fragmentIds.push(itemId);
        showTabWithoutAddingToBackStack(getFragment(item.getItemId()));
        return true;
    }
};

private Fragment getFragment(int fragmentId) {
    switch (fragmentId) {
        case R.id.action_home:
            return homeFragment;
        case R.id.action_favorites:
            return favouriteFragment;
        case R.id.action_nearme:
            return nearmeFragment;
    }
    return homeFragment;
}

private void showTabWithoutAddingToBackStack(Fragment fragment) {
    getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment, fragment.getClass().getSimpleName()).commit();
}

@Override
public void onBackPressed() {
    if(fragmentIds.getLast() != R.id.action_home){
            fragmentIds.addLast(R.id.action_home);
    }
    fragmentIds.pop();
    bottomNavigationView.getMenu().getItem(fragmentIds.size()-1).setChecked(true);
    if (!fragmentIds.isEmpty()) {
        showTabWithoutAddingToBackStack(getFragment(fragmentIds.peek()));
    } else {
        finish();
    }
}

对于 Kotlin 用户可以帮助此代码:

首先创建一个FragmentManager扩展class

fun FragmentManager.replace(containerId: Int, fragment: Fragment, tag: String) {
var current = findFragmentByTag(tag)
beginTransaction()
    .apply {
        //Hide the current fragment
        primaryNavigationFragment?.let { hide(it) }

        //Check if current fragment exists in fragmentManager
        if (current == null) {
            current = fragment
            add(containerId, current!!, tag)
        } else {
            show(current!!)
        }
    }
    .setTransition(FragmentTransaction.TRANSIT_ENTER_MASK)
    .setPrimaryNavigationFragment(current)
    .setReorderingAllowed(true)
    .commitNowAllowingStateLoss()

}

现在只需在您的

上调用它
 onNavigationItemSelected



supportFragmentManager.replace(R.id.fragment_id,YourFragmentClass,yourFragment.TAG) 

我有同样的问题,但我通过创建多个片段主机解决了它,然后我在 fragmentHost 中添加了片段。当底部导航 itemSelected 时,我只是使所需的主机片段可见,而其他主机片段主机可见性消失了。

这个方法可能有误,但对我来说很管用。 而且我们不必手动处理片段的状态,只需要处理 activity 的背压。 但是这个方法不会暂停片段。

而且我不知道如何处理片段的暂停和恢复所以请回复我。

也许这会对你有所帮助。

这是我的 fragmentHosts 主页 Activity:

<androidx.fragment.app.FragmentContainerView
        android:id="@+id/homeFragmentHost"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_NavBar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:visibility="gone"/>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/libraryFragmentHost"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_NavBar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:visibility="gone"/>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/myStuffFragmentHost"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_NavBar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:visibility="gone"/>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/moreFragmentHost"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_NavBar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:visibility="gone"/>

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_NavBar"
        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/app_bottom_nav_menu"
        tools:ignore="BottomAppBar" />

首页Activity onCreate:

supportFragmentManager.beginTransaction().replace(R.id.homeFragmentHost,HomeFragment()).commitNow()
    supportFragmentManager.beginTransaction().replace(R.id.libraryFragmentHost,LibraryFragment()).commitNow()
    supportFragmentManager.beginTransaction().replace(R.id.myStuffFragmentHost,MyStuffFragment()).commitNow()
    supportFragmentManager.beginTransaction().replace(R.id.moreFragmentHost,MoreFragment()).commitNow()
    homeFragmentHost.visibility = View.VISIBLE

底部导航项目选定的侦听器

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
    return when(item.itemId){
        R.id.homeFragment -> loadFragmentHost(homeFragmentHost)
        R.id.libraryFragment -> loadFragmentHost(libraryFragmentHost)
        R.id.myStuffFragment -> loadFragmentHost(myStuffFragmentHost)
        R.id.moreFragment -> loadFragmentHost(moreFragmentHost)
        else -> false
    }

loadFragmentHost 函数

    private fun loadFragmentHost(view:FragmentContainerView): Boolean {
    val list = arrayListOf(homeFragmentHost,libraryFragmentHost,myStuffFragmentHost,moreFragmentHost)
    list.remove(view)
    view.visibility = View.VISIBLE
    list.forEach {
        it.visibility = View.GONE
    }
    return true
}
public class MainActivity extends AppCompatActivity {

    boolean doubleBackToExitPressedOnce = false;
    final Fragment fragment1 = new HomeFragment();
    final Fragment fragment2 = new DashboardFragment();
    final Fragment fragment3 = new NotificationsFragment();
    final FragmentManager fm = getSupportFragmentManager();
    Fragment active = fragment1;
    BottomNavigationView navigation;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
        setFragment(fragment1, "1", 0);
    }


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

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    setFragment(fragment1, "1", 0);
                    return true;
                case R.id.navigation_dashboard:
                    setFragment(fragment2, "2", 1);
                    return true;
                case R.id.navigation_notifications:
                    setFragment(fragment3, "3", 2);
                    return true;
            }
            return false;
        }
    };

    public void setFragment(Fragment fragment, String tag, int position) {
        if (fragment.isAdded()) {
            fm.beginTransaction().hide(active).show(fragment).commit();
        } else {
            fm.beginTransaction().add(R.id.main_container, fragment, tag).commit();
        }
        navigation.getMenu().getItem(position).setChecked(true);
        active = fragment;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_settings) {
            startActivity(new Intent(MainActivity.this, SettingsActivity.class));
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
        if (active == fragment1) {
            if (doubleBackToExitPressedOnce) {
                super.onBackPressed();
                return;
            }
            this.doubleBackToExitPressedOnce = true;
            Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
        } else {
            setFragment(fragment1, "1", 0);
        }
    }
}
  1. 维护底部sheet片段Reusable
  2. BackPress 维护
  3. 双击退出
public class MainActivity extends AppCompatActivity {
    BottomNavigationView bottomNavigationView;
    Toaster toaster;
    private final Fragment androidFragment = new AndroidFragment();
    private final Fragment settingsFragment = new SettingsFragment();
    Fragment active;    
    String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    toaster = new Toaster(this);
    bottomNavigationView = findViewById(R.id.bottom_navigation);
    renderFragment(androidFragment, "android");
    active = androidFragment;
    bottomNavigationView.setOnItemSelectedListener(
            item -> {
                Log.e(TAG, "onCreate: " + active );
                if(item.getItemId() == R.id.action_android){
                    renderFragment(androidFragment, "android");
                    return true;
                }
                else if(item.getItemId() == R.id.action_settings){
                    renderFragment(settingsFragment, "settings");
                    return true;
                }
                return false;
            }
    );
}

private void renderFragment(Fragment fragment, String tag){
    FragmentManager fragmentManager = getSupportFragmentManager();
    if(fragment.isAdded()){
        fragmentManager.beginTransaction().hide(active).show(fragment)
                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).commit();
    }
    else {
        if(active != null){
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container_view, fragment, tag)
                    .hide(active)
                    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).commit();
        }
        else {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container_view, fragment, tag)
                    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).commit();
        }
    }
    active = fragment;
}
}

伙计们,这对我有用。