在 BottomNavigationBar 的帮助下在片段之间滑动

Swipe between fragments with help of BottomNavigationBar

我很难找到一个很好的例子来说明如何在 bottom navigatiom bar 的帮助下在 fragments 之间滑动。自 FragmentStatePagerAdapter is deprecated and a new ViewPager2 is now recommended instead of the old ViewPager I want to use ViewPager2 and FragmentStateAdapter in my code instead. I have found an example of how to combine BottomNavigationBar and ViewPager and I want to do something similar. My code have many similarities to the one in the example with the only difference that I have my code in a fragment instead of an activity. Here is a picture of how my FrontendFragment display look like。我可以使用 bottomnavigationbar 在视图之间切换,但我也希望能够在视图之间滑动。有人可以帮助我或至少以正确的方式指导我吗?这是我的代码:

FragmentPagerAdapter Class:

public class FragmentPagerAdapter extends FragmentStateAdapter {

    private static final int mFragmentCount = 5;

    public FragmentPagerAdapter(@NonNull Fragment fragment) {
        super(fragment);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        switch (position){

            case 0:
                return new HomeFragment();
            case 1:
                return new SearchFragment();
            case 2:
                return new AddFragment();
            case 3:
                return new MessageFragment();
            case 4:
                return new ProfileFragment();
        }
        return null;
    }

    @Override
    public int getItemCount() {
        return mFragmentCount;
    }
} 

前端片段Class:

public class FrontendFragment extends Fragment implements BottomNavigationView.OnNavigationItemSelectedListener{

    private BottomNavigationView mBottomNavigationView;
    private ViewPager2 mViewPager2;
    private FragmentPagerAdapter mFragmentPagerAdapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View v =  inflater.inflate(R.layout.fragment_frontend, container, false);

        loadFragment(new HomeFragment());

        mBottomNavigationView = v.findViewById(R.id.bottomNavigationBar);
        mBottomNavigationView.setOnNavigationItemSelectedListener(this);


        return v;
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {

        Fragment selectedFragment = null;

        switch (item.getItemId()) {
            case R.id.home_icon:
                selectedFragment = new HomeFragment();
                break;
            case R.id.search_icon:
                selectedFragment = new SearchFragment();
                break;
            case R.id.add_icon:
                selectedFragment = new AddFragment();
                break;

            case R.id.message_icon:
                selectedFragment = new MessageFragment();
                break;

            case R.id.profile_icon:
                selectedFragment = new ProfileFragment();
                break;
        }
        
        return loadFragment(selectedFragment);
    }


    private boolean loadFragment(Fragment selectedFragment) {

        if(selectedFragment != null){

            MainActivity.sFm.beginTransaction().replace(R.id.relLayoutMiddle, selectedFragment).commit();
            return true;
        }
        return false;
    }
}

提前致谢!

如果您想在视图之间滑动,一个简单的解决方案是将所有视图存储在您的父视图中,但将除初始视图之外的所有视图布局设置为 android:visibility="gone"。不过请确保将初始视图布局设置为 android:visibility="visible"。现在在您单击按钮时,您将必须实现 onClick 以便它们相应地打开/关闭视图可见性。例如,按顺序存储视图并通过数组索引控制它们。但是你试图做的整个事情通常不是一个好的设计模式 在我看来

你为什么不加载另一个 Activity onClick 而不是挤满你的单曲 activity?这将导致加载时间问题。即使视图是不可见的,将所有这些维护在一个地方也只是一个整体的麻烦。

因为我已经在我的一个应用程序中使用 BottomNav 和 ViewPager2,所以我可以提供帮助。

您的代码部分正确,这意味着您的 FragmentPagerAdapter 没问题,但您的 FrontEndFragment.

不正确

看,FragmentPagerAdapter 必须设置为 ViewPager2 as

//this here is the FrontEndFragment 
mViewPager2.setAdapter(new FragmentPagerAdapter(this));

那么,你根本不用做FragmentTransaction,你只需要通过BottomNavigationBar改变ViewPager2的当前项目位置为

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {

    switch (item.getItemId()) {
        case R.id.home_icon:
            mViewPager2.setCurrentItem(0);
            break;
        case R.id.search_icon:
            mViewPager2.setCurrentItem(1);
            break;
        case R.id.add_icon:
            mViewPager2.setCurrentItem(2);
            break;

        case R.id.message_icon:
            mViewPager2.setCurrentItem(3);
            break;

        case R.id.profile_icon:
            mViewPager2.setCurrentItem(4);
            break;
    }
    
    return false;
}

仅此而已,除了FragmentPagerAdapter,您根本不需要处理Fragments。另外,不要忘记删除不需要的 loadFragment(new HomeFragment());,也不需要函数 loadFragment()

(可选),此外,如果您想禁用 ViewPager2 的滑动操作,并希望仅根据 Selected BottomNav 项目选择片段,则可以设置 setUserInputEnabled() ViewPager2 的 属性 作为 false


接下来,要根据 ViewPager2 的滑动将 BottomNavigationBar 的项目设置为选中,您需要做的是,

创建全局变量

MenuItem previousMenuItem;

然后,在activity start as

上设置要选择的BottomNav 的默认项(第一个)
mBottomNavigationView.getMenu().getItem(0).setChecked(true);

最后,在 ViewPager2 上设置 OnPageSelected() 回调以将所选菜单项更新为:

mViewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        super.onPageScrolled(position, positionOffset, positionOffsetPixels);
    }

    @Override
    public void onPageSelected(int position) {
        super.onPageSelected(position);
        if (previousMenuItem != null) {
            previousMenuItem.setChecked(false);
        }
        else {
            mBottomNavigationView.getMenu().getItem(0).setChecked(false);
        }
        mBottomNavigationView.getMenu().getItem(position).setChecked(true);
        previousMenuItem = mBottomNavigationView.getMenu().getItem(position);
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        super.onPageScrollStateChanged(state);
    }
});

你在这里做的是将默认项目设置为 previousMenuItem 然后滑动到另一个页面,取消选择 previousMenuItem 并选择新的,这意味着更新基于 ViewPager 当前项目的 BottomNav。这是实现 objective.

所需的完整代码