Viewpager with different menu and common toolbar not working

前端 未结 1 1737
误落风尘
误落风尘 2020-12-29 16:48

I have tabs in my app. Each tab is of different fragments and has different menu. Below is the layout which I am using

    

        
相关标签:
1条回答
  • 2020-12-29 17:28

    I have written small test-application to check the behaviour.

    Let's go through the sample and see, if something wrong with your fragments (as you see above, ViewPager with different menus works like a charm)

    Activity's XML:

    <?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">
    
        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
        <android.support.v4.view.ViewPager
            android:id="@+id/viewPager"
            android:layout_below="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </RelativeLayout>
    

    Activity class. Important part is invalidateOptionsMenu() every time ViewPager has PageSelected event. Then, we setting setHasOptionsMenu to all fragments and subfragments(from the nested ViewPagers) to false if they out of screen.

    public class MainActivity extends AppCompatActivity {
    
        PagerAdapter pagerAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Fragment[] fragments = {
                    Fragment.instantiate(this, FragmentNoMenu.class.getName()),
                    Fragment.instantiate(this, FragmentA.class.getName()),
                    Fragment.instantiate(this, FragmentNoMenu.class.getName()),
                    Fragment.instantiate(this, FragmentB.class.getName()),
            };
    
            TabLayout tabLayout = (TabLayout)findViewById(R.id.tabLayout);
            ViewPager viewPager = (ViewPager)findViewById(R.id.viewPager);
            pagerAdapter = new PagerAdapter(getSupportFragmentManager(), fragments);
            viewPager.setAdapter(pagerAdapter);
            viewPager.setOffscreenPageLimit(0);
            viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
                @Override
                public void onPageSelected(int position) {
                    invalidateOptionsMenu(position);
                }
                @Override
                public void onPageScrollStateChanged(int state) {}
            });
    
            invalidateOptionsMenu(0);
            tabLayout.setupWithViewPager(viewPager);
        }
    
        private void invalidateOptionsMenu(int position) {
            for(int i = 0; i < pagerAdapter.getCount(); i++) {
                Fragment fragment = pagerAdapter.getItem(i);
                fragment.setHasOptionsMenu(i == position);
    
                if (fragment instanceof FragmentWithViewPager) {
                    FragmentWithViewPager fragmentWithViewPager = (FragmentWithViewPager)fragment;
                    if (fragmentWithViewPager.pagerAdapter != null) {
                        for (int j = 0; j < fragmentWithViewPager.pagerAdapter.getCount(); j++) {
                            fragmentWithViewPager.pagerAdapter.getItem(j).setHasOptionsMenu(i == position);
                        }
                    }
                }
            }
    
            invalidateOptionsMenu();
        }
    }
    

    PagerAdapter class:

    public class PagerAdapter extends FragmentPagerAdapter {
    
        private final Fragment[] fragments;
    
        public PagerAdapter(FragmentManager fragmentManager, Fragment[] fragments) {
            super(fragmentManager);
            this.fragments = fragments;
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return fragments[position].getClass().getSimpleName();
        }
    
        @Override
        public Fragment getItem(int position) {
            return fragments[position];
        }
    
        @Override
        public int getCount() {
            return fragments.length;
        }
    }
    

    Here're my test fragments I used:

    FragmentNoMenu class:

    public class FragmentNoMenu extends android.support.v4.app.Fragment {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fragment_no_menu, container, false);
        }
    }
    

    FragmentNoMenu layout:

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

    FragmentA class is a Fragment with nested ViewPager:

    public class FragmentA extends FragmentWithViewPager {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_a, container, false);
    
            Fragment[] fragments = {
                    Fragment.instantiate(getContext(), SubFragmentA.class.getName()),
                    Fragment.instantiate(getContext(), SubFragmentB.class.getName()),
                    Fragment.instantiate(getContext(), SubFragmentC.class.getName()),
            };
    
            if (pagerAdapter == null) {
                pagerAdapter = new PagerAdapter(getChildFragmentManager(), fragments);
            }
    
            viewPager = (ViewPager)rootView.findViewById(R.id.viewPager);
            viewPager.setAdapter(pagerAdapter);
            return rootView;
        }
    
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            inflater.inflate(R.menu.fragment_a, menu);
            super.onCreateOptionsMenu(menu, inflater);
        }
    }
    

    FragmentA's layout:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:background="#B0B0B0"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.support.v4.view.ViewPager
            android:id="@+id/viewPager"
            android:layout_marginTop="80dp"
            android:layout_width="match_parent"
            android:layout_height="200dp"/>
    </FrameLayout>
    

    FragmentA's menu:

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <item
            android:id="@+id/action_item_1"
            android:title="Item 1"
            android:orderInCategory="250"
            app:showAsAction="never" />
    
        <item
            android:id="@+id/action_item_2"
            android:title="Item 2"
            android:orderInCategory="300"
            app:showAsAction="never" />
    </menu>
    

    NB! FragmentA extends FragmentWithViewPager - it's a small extension of Fragment to make it easier to distinguish Fragments with nested fragments in MainActivity:

    public class FragmentWithViewPager extends Fragment {
        PagerAdapter pagerAdapter;
        ViewPager viewPager;
    }
    

    FragmentB:

    public class FragmentB extends Fragment {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fragment_b, container, false);
        }
    
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            inflater.inflate(R.menu.fragment_b, menu);
            super.onCreateOptionsMenu(menu, inflater);
        }
    }
    

    It's layout & menu:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:background="#999999"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    
    .....
    
    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <item
            android:id="@+id/action_item3"
            android:title="Item 3"
            android:icon="@drawable/ic_triage_star"
            android:orderInCategory="250"
            app:showAsAction="always" />
    </menu>
    

    Subfragments (they are all look the same from the code perspective):

    Layouts:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:background="#AA0000"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:text="SubFragment C (with icon Menu)"
            android:textSize="24sp"
            android:textColor="#00BB00"
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </FrameLayout>
    

    Code:

    public class SubFragmentB extends Fragment {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            return inflater.inflate(R.layout.subfragment_b, container, false);
        }
    }
    

    That's it! I've uploaded the project to my dropbox - feel free to check it out!

    I hope, it helps

    0 讨论(0)
提交回复
热议问题