android - How to implement a ViewPager with different Fragments / Layouts

android - How to implement a ViewPager with different Fragments / Layouts

Bóthildr Vilma Author: Bóthildr Vilma Date: 2022-08-15
android - How to implement a ViewPager with different Fragments / Layouts

All you need to know about android - How to implement a ViewPager with different Fragments / Layouts , in addintion to How to swap fragments with different layouts in android? , android - How to delete a tab with actionbar, viewpager, and multiple fragments? , Showing/Hiding menu items in viewPager fragments WITHOUT DELAY (Android) , java - ANDROID: ViewPager with different Fragments in instantiateItem method

  1. android - How to implement a ViewPager with different Fragments / Layouts
  2. Question:

    When I start an activity which implements viewpager, the viewpager created various fragments. I want to use different layouts for each fragment, but the problem is that viewpager shows only two layouts at the max (second layout on all of the remaining fragments after 1).

    Here is the code for SwipeActivity which implements the viewpager :

    public class SwipeActivity extends FragmentActivity
    {
    
        MyPageAdapter pageAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_swipe);
            pageAdapter = new MyPageAdapter(getSupportFragmentManager());
            ViewPager pager=(ViewPager)findViewById(R.id.pager);
            pager.setAdapter(pageAdapter);
            ActionBar bar = getActionBar();
            bar.setDisplayHomeAsUpEnabled(true);
        }
        /**
        * Custom Page adapter
        */
        private class MyPageAdapter extends FragmentPagerAdapter
        {
            public MyPageAdapter(FragmentManager fm)
            {
                super(fm);
            }
            @Override
            public int getCount()
            {
                return 5;
            }
            @Override
            public Fragment getItem(int position)
            {
                switch(position)
                {
                    case 0: return new MyFragment();
                    case 1: return SecondFragment.newInstance("asdasd");
                    default : return RamFragment.newInstance("s");
                }
            }
         }
    }
    

    Here is the code for the fragments

    public class MyFragment extends Fragment
    {
       @Override
       public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup,    Bundle paramBundle)
       {
         return paramLayoutInflater.inflate(R.layout.processorlayout, paramViewGroup, false);
       }
    }
    

    I used 5 fragments like this, all having different layouts, but the viewpager shows only 2 at the max.

    EDIT : code for SecondFragment

    public class SecondFragment extends Fragment
    {
       public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
    
      public static final SecondFragment newInstance(String paramString)
      {
        SecondFragment f = new SecondFragment();
        Bundle localBundle = new Bundle(1);
        localBundle.putString("EXTRA_MESSAGE", paramString);
        f.setArguments(localBundle);
        return f;
      }
    
      @Override
      public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle)
      {
         return paramLayoutInflater.inflate(R.layout.motherboardlayout, paramViewGroup, false);
      }
    }
    


    Solution 1:

    As this is a very frequently asked question, I wanted to take the time and effort to explain the ViewPager with multiple Fragments and Layouts in detail. Here you go.

    ViewPager with multiple Fragments and Layout files - How To

    The following is a complete example of how to implement a ViewPager with different fragment Types and different layout files.

    In this case, I have 3 Fragment classes, and a different layout file for each class. In order to keep things simple, the fragment-layouts only differ in their background color. Of course, any layout-file can be used for the Fragments.

    FirstFragment.java has a orange background layout, SecondFragment.java has a green background layout and ThirdFragment.java has a red background layout. Furthermore, each Fragment displays a different text, depending on which class it is from and which instance it is.

    Also be aware that I am using the support-library's Fragment: android.support.v4.app.Fragment

    MainActivity.java (Initializes the Viewpager and has the adapter for it as an inner class). Again have a look at the imports. I am using the android.support.v4 package.

    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.support.v4.view.ViewPager;
    
    public class MainActivity extends FragmentActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);     
    
            ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
            pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
        }
    
        private class MyPagerAdapter extends FragmentPagerAdapter {
    
            public MyPagerAdapter(FragmentManager fm) {
                super(fm);
            }
    
            @Override
            public Fragment getItem(int pos) {
                switch(pos) {
    
                case 0: return FirstFragment.newInstance("FirstFragment, Instance 1");
                case 1: return SecondFragment.newInstance("SecondFragment, Instance 1");
                case 2: return ThirdFragment.newInstance("ThirdFragment, Instance 1");
                case 3: return ThirdFragment.newInstance("ThirdFragment, Instance 2");
                case 4: return ThirdFragment.newInstance("ThirdFragment, Instance 3");
                default: return ThirdFragment.newInstance("ThirdFragment, Default");
                }
            }
    
            @Override
            public int getCount() {
                return 5;
            }       
        }
    }
    

    activity_main.xml (The MainActivitys .xml file) - a simple layout file, only containing the ViewPager that fills the whole screen.

    <android.support.v4.view.ViewPager
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/viewPager"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />
    

    The Fragment classes, FirstFragment.java import android.support.v4.app.Fragment;

    public class FirstFragment extends Fragment {
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.first_frag, container, false);
    
            TextView tv = (TextView) v.findViewById(R.id.tvFragFirst);
            tv.setText(getArguments().getString("msg"));
    
            return v;
        }
    
        public static FirstFragment newInstance(String text) {
    
            FirstFragment f = new FirstFragment();
            Bundle b = new Bundle();
            b.putString("msg", text);
    
            f.setArguments(b);
    
            return f;
        }
    }
    

    first_frag.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:background="@android:color/holo_orange_dark" >
    
        <TextView
            android:id="@+id/tvFragFirst"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:textSize="26dp"
            android:text="TextView" />
    </RelativeLayout>
    

    SecondFragment.java

    public class SecondFragment extends Fragment {
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.second_frag, container, false);
    
        TextView tv = (TextView) v.findViewById(R.id.tvFragSecond);
        tv.setText(getArguments().getString("msg"));
    
        return v;
    }
    
    public static SecondFragment newInstance(String text) {
    
        SecondFragment f = new SecondFragment();
        Bundle b = new Bundle();
        b.putString("msg", text);
    
        f.setArguments(b);
    
        return f;
    }
    }
    

    second_frag.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:background="@android:color/holo_green_dark" >
    
        <TextView
            android:id="@+id/tvFragSecond"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:textSize="26dp"
            android:text="TextView" />
    
    </RelativeLayout>
    

    ThirdFragment.java

    public class ThirdFragment extends Fragment {
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.third_frag, container, false);
    
        TextView tv = (TextView) v.findViewById(R.id.tvFragThird);      
        tv.setText(getArguments().getString("msg"));
    
        return v;
    }
    
    public static ThirdFragment newInstance(String text) {
    
        ThirdFragment f = new ThirdFragment();
        Bundle b = new Bundle();
        b.putString("msg", text);
    
        f.setArguments(b);
    
        return f;
    }
    }
    

    third_frag.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:background="@android:color/holo_red_light" >
    
        <TextView
            android:id="@+id/tvFragThird"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:textSize="26dp"
            android:text="TextView" />
    
    </RelativeLayout>
    

    The end result is the following:

    The Viewpager holds 5 Fragments, Fragments 1 is of type FirstFragment, and displays the first_frag.xml layout, Fragment 2 is of type SecondFragment and displays the second_frag.xml, and Fragment 3-5 are of type ThirdFragment and all display the third_frag.xml.

    enter image description here

    Above you can see the 5 Fragments between which can be switched via swipe to the left or right. Only one Fragment can be displayed at the same time of course.

    Last but not least:

    I would recommend that you use an empty constructor in each of your Fragment classes.

    Instead of handing over potential parameters via constructor, use the newInstance(...) method and the Bundle for handing over parameters.

    This way if detached and re-attached the object state can be stored through the arguments. Much like Bundles attached to Intents.

    Solution 2:

    Create an array of Views and apply it to: container.addView(viewarr[position]);

    public class Layoutes extends PagerAdapter {
    
        private Context context;
        private LayoutInflater layoutInflater;
        Layoutes(Context context){
            this.context=context;
        }
        int layoutes[]={R.layout.one,R.layout.two,R.layout.three};
        @Override
        public int getCount() {
            return layoutes.length;
        }
    
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return (view==(LinearLayout)object);
        }
        @Override
        public Object instantiateItem(ViewGroup container, int position){
            layoutInflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View one=layoutInflater.inflate(R.layout.one,container,false);
            View two=layoutInflater.inflate(R.layout.two,container,false);
            View three=layoutInflater.inflate(R.layout.three,container,false);
            View viewarr[]={one,two,three};
            container.addView(viewarr[position]);
            return viewarr[position];
        }
        @Override
        public void destroyItem(ViewGroup container, int position, Object object){
            container.removeView((LinearLayout) object);
        }
    
    }
    

    Solution 3:

    Code for adding fragment

    public Fragment getItem(int position) {
    
        switch (position){
            case 0:
                return new Fragment1();
    
            case 1:
                return new Fragment2();
    
            case 2:
                return new Fragment3();
    
            case 3:
                return new Fragment4();
    
            default:
                break;
        }
    
        return null;
    }
    

    Create an xml file for each fragment say for Fragment1, use fragment_one.xml as layout file, use the below code in Fragment1 java file.

    public class Fragment1 extends Fragment {
    
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    
            View view = inflater.inflate(R.layout.fragment_one, container, false);
    
            return view;
    
        }
    }
    

    Later you can make necessary corrections.. It worked for me.

  3. How to swap fragments with different layouts in android?
  4. Question:

    I'm developing an android application making use of fragments which is more of a Master/Detail form. I want the main activity to consist of a list fragment on the left side, based on the item chosen on the left i want to display a fragment with different layout on the right side. (Note: each fragment on the right require different layouts/views)

    All the examples that I've come across make use of only one common fragment on the right by changing some values in it or swapping/replacing new fragments having same layout.

    If someone could shed some light on this problem then it will help me immensely. Thanks!


    Solution 1:

    If you are using framelayouts to hold your fragments, it's the same as those other you mention. You just instantiate your fragment (whatever the layout) and swap it into the framelayout in place of the other one.

    If you have hardcoded your fragments into the XML, you won't be able to do that (as far as I've been able to determine).

    main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/frames"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/hline1"
        android:layout_below="@id/horizontalline"
        android:orientation="horizontal" >
        <FrameLayout
            android:id="@+id/leftpane"
            android:layout_width="0px"
            android:layout_height="match_parent"
            android:layout_weight=".4" />
        <TextView
            android:id="@+id/verticalline"
            android:layout_width="2dp"
            android:layout_height="match_parent"
            android:background="@color/bar_background"
            android:gravity="center_horizontal"
            android:paddingLeft="5dip"
            android:paddingRight="5dip" />
        <FrameLayout
            android:id="@+id/rightpane"
            android:layout_width="0px"
            android:layout_height="match_parent"
            android:layout_weight="1" >
        </FrameLayout>
    </LinearLayout>
    

    Then you use the id for the framelayout and the name of your instantiated fragment to put your fragment into the framelayout.

    EventListFragment eventlist = new EventListFragment();
    getFragmentManager().beginTransaction().replace(R.id.leftpane, eventlist).commit();
    
    EventDetailFragment eventadd = new EventDetailFragment();
    getFragmentManager().beginTransaction().replace(R.id.rightpane, eventadd).commit();
    

    When you want to change the contents, you do the same thing again (the following would replace the fragment in the right pane with a new/different fragment, which can have it's own, different, layout associated with it):

    EventSuperDetailFragment eventsuper = new EventSuperDetailFragment();
    getFragmentManager().beginTransaction().replace(R.id.rightpane, eventsuper).commit();
    

  5. android - How to delete a tab with actionbar, viewpager, and multiple fragments?
  6. Question:

    I'm using code I found here.

    public class ActionBarTabs extends SherlockFragmentActivity {
    CustomViewPager mViewPager;
    TabsAdapter mTabsAdapter;
    TextView tabCenter;
    TextView tabText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    
        mViewPager = new CustomViewPager(this);
        mViewPager.setId(R.id.pager);
    
        setContentView(mViewPager);
        ActionBar bar = getSupportActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
    
        mTabsAdapter = new TabsAdapter(this, mViewPager);
    
        mTabsAdapter.addTab(bar.newTab().setText("Home"),
                ToolKitFragment.class, null);
        mTabsAdapter.addTab(bar.newTab().setText("FujiSan"),
                FujiFragment.class, null);
    }
    
    public static class TabsAdapter extends FragmentPagerAdapter implements
            ActionBar.TabListener, ViewPager.OnPageChangeListener {
        private final Context mContext;
        private final ActionBar mActionBar;
        private final ViewPager mViewPager;
        private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
    
        static final class TabInfo {
            private final Class<?> clss;
            private final Bundle args;
    
            TabInfo(Class<?> _class, Bundle _args) {
                clss = _class;
                args = _args;
            }
        }
    
        public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager) {
            super(activity.getSupportFragmentManager());
            mContext = activity;
            mActionBar = activity.getSupportActionBar();
            mViewPager = pager;
            mViewPager.setAdapter(this);
            mViewPager.setOnPageChangeListener(this);
        }
    
        public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
            TabInfo info = new TabInfo(clss, args);
            tab.setTag(info);
            tab.setTabListener(this);
            mTabs.add(info);
            mActionBar.addTab(tab);
            notifyDataSetChanged();
        }
    
        @Override
        public int getCount() {
            return mTabs.size();
        }
    
        @Override
        public Fragment getItem(int position) {
            TabInfo info = mTabs.get(position);
            return Fragment.instantiate(mContext, info.clss.getName(),
                    info.args);
        }
    
        @Override
        public void onPageScrolled(int position, float positionOffset,
                int positionOffsetPixels) {
        }
    
        @Override
        public void onPageSelected(int position) {
            mActionBar.setSelectedNavigationItem(position);
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
        }
    
        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            Object tag = tab.getTag();
            for (int i = 0; i < mTabs.size(); i++) {
                if (mTabs.get(i) == tag) {
                    mViewPager.setCurrentItem(i);
                }
            }
        }
    
        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        }
    
        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) {
        }
    }
    }
    

    I'm trying to modify it so that I can delete tabs dynamically. I tried by simply creating this function:

        public void removeTab(ActionBar.Tab tab) {
            mTabs.remove(tab);
            mActionBar.removeTab(tab);
            notifyDataSetChanged();
        }
    

    But I always get an indexoutofboundsexception. Does anyone know a good way to do this?

    EDIT

    By changing my method to:

        public void removeTab(ActionBar.Tab tab) {
            mTabs.remove(tab.getTag());
            mActionBar.removeTab(tab);
            notifyDataSetChanged();
        }
    

    I was able to successfully remove tabs. However, when I delete a tab that IS NOT the one on the far right, the view (or fragment?) that was associated with the tab doesn't go away. Instead, it seems to become associated with the next highest tab. For instance, if I deleted tab 0, tab 0's view just moves to tab 1. If I delete the tab with the highest ID then the tab and view go away correctly but then COME BACK when I add a new tab.

    It's as if there's a list of fragments somewhere that is being associated with the tabs and deleting the tab doesn't delete the fragment. Does anyone have any idea what's causing this?

    EDIT2

    I've tried to delete the fragments with:

                Fragment fragmentToRemove = getItem(tab.getPosition());
                destroyItem(mViewPager, tab.getPosition(), fragmentToRemove);
    

    and also

            Fragment fragmentToRemove = getItem(tab.getPosition());
            FragmentTransaction fragmentTransaction = mActivity
                    .getSupportFragmentManager().beginTransaction();
            fragmentTransaction.remove(fragmentToRemove);
            fragmentTransaction.commit();
    

    But neither has worked so far.


    Solution 1:

    Got it!

    public void removeTab(ActionBar.Tab tab) {
        mTabs.remove(tab.getTag());
        mActionBar.removeTab(tab);
        notifyDataSetChanged();
    }
    

    and override destroyItem

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            // TODO Auto-generated method stub
            super.destroyItem(container, position, object);
            FragmentManager manager = ((Fragment) object).getFragmentManager();
            FragmentTransaction trans = manager.beginTransaction();
            trans.remove((Fragment) object);
            trans.commit();
        }
    

    Works perfectly!!!

    Solution 2:

    Solution 3:

    Ok - this one ate my lunch for 2 weeks. I didn't find that the above worked for me at all exactly as shown. I am using Android Studio 3.5.1 in case that matters.

    What follows is my FragmentPagerAdapter code in its entirety. It contains most everything you should need. The Fragment code is fairly straightforward for whatever each of your fragments contains. But let me know if more is required or if you have any questions.

    Also, if you have any comments or find any errors, please post a comment. I hope this helps others.

    import android.content.Context;
    import android.view.ViewGroup;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentManager;
    import androidx.fragment.app.FragmentPagerAdapter;
    import androidx.fragment.app.FragmentTransaction;
    import androidx.viewpager.widget.ViewPager;
    
    import com.google.android.material.tabs.TabLayout;
    
    import java.util.ArrayList;
    
    public class ChecklistPagerAdapter extends FragmentPagerAdapter {
    
        private final Context mContext;
        private int currentTabPosition = -1;
        ArrayList<String> tabNames = new ArrayList<>();
        ArrayList<Fragment> fragments = new ArrayList<>();
    
        public ChecklistPagerAdapter(Context context, FragmentManager fm) {
            super(fm);
            mContext = context;
        }
    
        public void add(Fragment fragment, String title) {
            tabNames.add(title);
            fragments.add(fragment);
        }
    
        public int getCurrentTabPosition() {
            return currentTabPosition;
        }
    
        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }
    
        @Override
        public int getItemPosition(@NonNull Object object) {
            ChecklistFragment fragment = (ChecklistFragment) object;
            for (int i = 0; i < fragments.size(); i++) {
                if (fragments.get(i).equals(fragment)) {
                    return i;
                }
            }
            return POSITION_NONE;
        }
    
        @Override
        public long getItemId(int position) {
            return fragments.get(position).hashCode();
        }
    
        @Override
        public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            super.setPrimaryItem(container, position, object);
            currentTabPosition = position;
        }
    
        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            return tabNames.get(position);
        }
    
        @Override
        public int getCount() {
            return fragments.size();
        }
    
        public void removeTab(TabLayout tabLayout, ViewPager viewPager, DBHelper dbHelper) {
            // Get current tab position as it changes below
            int position = currentTabPosition;
    
            // Get current fragment representing curTab
            ChecklistFragment fragment = (ChecklistFragment) fragments.get(position);
    
            // Remove Tab
            tabLayout.removeTabAt(position);
    
            // Remove from ArrayLists
            fragments.remove(position);
            tabNames.remove(position);
    
            // Remove fragment
            FragmentManager fragmentManager = fragment.getFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.remove(fragment);
            fragmentTransaction.commit();
    
            // Refresh
            tabLayout.invalidate();
            notifyDataSetChanged();
    
            // Remove all records from ChecklistTab table
            dbHelper.clearChecklistTab(fragment.getOutingId(), fragment.getChecklistId());
        }
    }
    

  7. Showing/Hiding menu items in viewPager fragments WITHOUT DELAY (Android)
  8. Question:

    I am aware that similar questions have been posted on this site many times before, HOWEVER, my question is not how I can show/hide menu items in different fragments. I got that down. The problem is there is a delay between swiping fragments and the new menu items showing or hiding. This delay really detracts from the interface. The changes in the action bar menu items should be immediate, amongst other reasons, to avoid clicking certain menu items in the wrong fragment.

    So question is, how can i change the menu items in the actionbar immediately when the user begins swiping the fragment to go to the next?

    I know it's possible because various applications already do this. I am currently overriding the onPrepareOptionsMenu() method in every fragment and telling it which items to show and which to hide. I use supportInvalidateOptionsMenu() method to prompt the changing of the menu items, but the lag is still too long and evident.

    I am open to changing the structure/technique of my changing of the menu items in the fragment in order to achieve an IMMEDIATE change in the menu times as soon as the swiping begins.

    Please help. Thanks!


    Solution 1:

    Ok, so after looking everywhere, and finding similar posts by other people with no true answer, I have finally figured out how to invalidate the action bar menu as soon as the pages are swiped. You want to do this in an onPageChangeListener in your activity's onCreate method as below:

    yourViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() 
    {
        @Override
        public void onPageSelected(int position) 
        {
            //Clear action bar menu items. 
            //This prompts the onPrepareOptionsMenu which recreates the menu with
            //with the appropriate options for a given fragment as defined by you 
            supportInvalidateOptionsMenu();
        }
    
        @Override
        public void onPageScrollStateChanged (int arg0)
        {
            //Clear action bar menu items and display correct ones
            //This invalidates the menu options as soon as the swiping of pages begins
            supportInvalidateOptionsMenu();
        }
    }
    

    So the onPageScrollStateChanged method is what you really want whenever you want the page swiping to trigger a specified action.

    Solution 2:

    a possible solution for this problem would be inflating your custom menu inside the activity hosts your ViewPager and getting a menu reference as below:

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

    after that you can easily hide/show the menu's items without any delay inside onPageSelected method as below:

     @Override
     public void onPageSelected(int position) {
      switch (position) {
            case 0: { 
               customMenu.getItem(0).setVisible(false);
               break;
            }
           case 1: { 
               customMenu.getItem(0).setVisible(true);
                 break;
            }
         }
    

  9. java - ANDROID: ViewPager with different Fragments in instantiateItem method
  10. Question:

    I use ViewPager to create fragments that swipe left and now I want insert fragments into each fragment page.

    activityMain.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout
        ...
        android:orientation="vertical">
    
        <android.support.v4.view.ViewPager
            android:id="@+id/myviewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    
        <devlight.io.library.ntb.NavigationTabBar
            android:id="@+id/ntb_horizontal"
            app:ntb_swiped="true"/>
    
    
    </android.support.design.widget.CoordinatorLayout>
    

    and this: tab0_fragment.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp"
            android:textSize="30sp"
            android:gravity="center"
            android:id="@+id/textView"
            android:layout_centerHorizontal="true"
            android:textColor="@android:color/holo_green_dark"
            android:text="Social\nFragment"/>
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:autoLink="web"
            android:textSize="15sp"
            android:layout_marginTop="10dp"
            android:layout_centerHorizontal="true"
            android:text="androidbelieve.com"
            android:textColor="#000"
            android:layout_below="@+id/textView"
            android:textStyle="italic"/>
    
    </RelativeLayout>
    

    I have a ViewPager in mainActivity.java

    final ViewPager viewPager = (ViewPager) findViewById(R.id.myviewpager);
    viewPager.setAdapter(new PagerAdapter() {
    ...
    
    ...
    }
    

    I try open one screen in viewpager via fragment layout.

    I try this:

    final ViewPager viewPager = (ViewPager) findViewById(R.id.myviewpager);
    viewPager.setAdapter(new PagerAdapter() {
        ...
        public Object instantiateItem(final ViewGroup container, final int position) {
               if (position == 0)
               {
                    final View view = LayoutInflater.from(getBaseContext()).inflate(R.layout.fragment_tab0, null, false);
                    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
                    fragmentTransaction.replace(R.id.myviewpager,new tab0Fragment()).commit();
                    container.addView(view);
                    return view;
               }
               else if (position == 1)
               ...
    
       } 
    
    ...
    }
    

    AND tab0Fragment.java

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

    I am noob in android. how can correct this code?


    Solution: The answers was not my answer but that help me a lot.

    According @Mr. Rabbit ans @Amit Upadhyay I change top code to this:

    @Override
                public Object instantiateItem(final ViewGroup container, final int position) {
    
                    if (position == 0)
                    {
                        final View view = LayoutInflater.from(getBaseContext()).inflate(R.layout.fragment_tab0, null, false);
                        MyAdapter adapter = new MyAdapter(getSupportFragmentManager());
                        adapter.addFragment(new tab0Fragment(), getResources().getString(R.string.tab0));
                        container.addView(view);
                        return view;
                    }
                    else if (position == 1)
                    {
    

    and also adding MyAdapter class according @Mr. Rabbit's answer.

    hope help someone else.


    Solution 1:

    Try to separate out your adapter and below code.

    MyAdapter.java

    public class MyAdapter extends FragmentPagerAdapter{
    
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();
    
        public MyAdapter(FragmentManager fm) {
            super(fm);
        }
    
        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragmentList.size();
        }
    
    
        public void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }
    

    Create your Fragments

    FragmentOne.java

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

    FragmentTwo.java

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

    Setup your viewpager like this in your activity.

    final ViewPager viewPager = (ViewPager) findViewById(R.id.myviewpager);
        MyAdapter adapter = new MyAdapter(getSupportFragmentManager());
    
        // Add your fragments in adapter.
        FragmentOne fragmentOne = new FragmentOne();
        adapter.addFragment(fragmentOne, getResources().getString(R.string.fragment_one_title));
    
        FragmentTwo fragmentTwo = new FragmentTwo();
        adapter.addFragment(fragmentTwo, getResources().getString(R.string.fragment_two_title));
    
        viewPager.setAdapter(adapter);
    

    Then finally set your NavigationTabBar with your ViewPager.

    final NavigationTabBar navigationTabBar = (NavigationTabBar) findViewById(R.id.ntb_horizontal);
    navigationTabBar.setViewPager(viewPager, 2);
    

    Solution 2:

    To achieve this you can create a custom ViewPagerAdapter. Eg:

    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    
    import java.util.ArrayList;
    
    /**
     * Created by aupadhyay on 1/5/17.
     */
    
    public class ViewPagerAdapter extends FragmentPagerAdapter {
    
        ArrayList<Fragment> fragments = new ArrayList<>();
        ArrayList<String> tabTitles = new ArrayList<>();
    
        public void addFragments(Fragment fragment, String tabTitle)
        {
            this.fragments.add(fragment);
            this.tabTitles.add(tabTitle);
        }
    
        public ViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }
    
        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }
    
        @Override
        public int getCount() {
            return fragments.size();
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return tabTitles.get(position);
        }
    
    }
    

    Now you can set adapter on viewpager like this:

    final ViewPager viewPager = (ViewPager) findViewById(R.id.myviewpager);
    
    ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
    
            viewPagerAdapter.addFragments(new Tab0Fragment(), "First");
            viewPagerAdapter.addFragments(new Tab1Fragment(), "Second");
            viewPagerAdapter.addFragments(new Tab2Fragment(), "Third");
            // add more if required.
    
    viewPager.setAdapter(viewPagerAdapter);
    

    Tab0Fragment, Tab1Fragment, Tab1Fragment are the fragments created by you to add in your viewpager.