Add / Delete pages to ViewPager dynamically

前端 未结 9 1109
囚心锁ツ
囚心锁ツ 2021-01-29 23:17

I would like to add or delete pages from my view pager dynamically. Is that possible?

相关标签:
9条回答
  • 2021-01-29 23:53

    Here's an alternative solution to this question. My adapter:

    private class PagerAdapter extends FragmentPagerAdapter implements 
                  ViewPager.OnPageChangeListener, TabListener {
    
        private List<Fragment> mFragments = new ArrayList<Fragment>();
        private ViewPager mPager;
        private ActionBar mActionBar;
    
        private Fragment mPrimaryItem;
    
        public PagerAdapter(FragmentManager fm, ViewPager vp, ActionBar ab) {
            super(fm);
            mPager = vp;
            mPager.setAdapter(this);
            mPager.setOnPageChangeListener(this);
            mActionBar = ab;
        }
    
        public void addTab(PartListFragment frag) {
            mFragments.add(frag);
            mActionBar.addTab(mActionBar.newTab().setTabListener(this).
                                setText(frag.getPartCategory()));
        }
    
        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragments.size();
        }
    
        /** (non-Javadoc)
         * @see android.support.v4.app.FragmentStatePagerAdapter#setPrimaryItem(android.view.ViewGroup, int, java.lang.Object)
         */
        @Override
        public void setPrimaryItem(ViewGroup container, int position,
                Object object) {
            super.setPrimaryItem(container, position, object);
            mPrimaryItem = (Fragment) object;
        }
    
        /** (non-Javadoc)
         * @see android.support.v4.view.PagerAdapter#getItemPosition(java.lang.Object)
         */
        @Override
        public int getItemPosition(Object object) {
            if (object == mPrimaryItem) {
                return POSITION_UNCHANGED;
            }
            return POSITION_NONE;
        }
    
        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            mPager.setCurrentItem(tab.getPosition());
        }
    
        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) { }
    
        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) { }
    
        @Override
        public void onPageScrollStateChanged(int arg0) { }
    
        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) { }
    
        @Override
        public void onPageSelected(int position) {
            mActionBar.setSelectedNavigationItem(position);
        }
    
        /**
         * This method removes the pages from ViewPager
         */
        public void removePages() {
            mActionBar.removeAllTabs();
    
                        //call to ViewPage to remove the pages
            vp.removeAllViews();
            mFragments.clear();
    
            //make this to update the pager
            vp.setAdapter(null);
            vp.setAdapter(pagerAdapter);
        }
    }
    

    Code to remove and add dynamically

    //remove the pages. basically call to method removeAllViews from ViewPager
    pagerAdapter.removePages();
    
    pagerAdapter.addPage(pass your fragment);
    

    After the advice of Peri Hartman, it started to work after I set null to ViewPager adapter and put the adapter again after the views removed. Before this the page 0 doesn't showed its list contents.

    0 讨论(0)
  • 2021-01-29 23:53

    I am sure you have created an adapter by extending PageAdapter, so there is one method:

     @Override
     public void destroyItem(View collection, int position, Object view) {
               ((ViewPager) collection).removeView((View) view);
     }
    

    For detailed example for the same, just go through this example.

    0 讨论(0)
  • 2021-01-30 00:01

    Based on other answers and other resources I've ended with this code.

    CustomPagerAdapter:

    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v4.view.PagerAdapter;
    import android.view.View;
    import android.view.ViewGroup;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class CustomPagerAdapter extends PagerAdapter {
    
      private List<Fragment> pages = new ArrayList<>();
      private Map<Fragment, Integer> fragmentsPosition = new HashMap<>();
    
      private Fragment currentPrimaryItem;
      private FragmentManager fragmentManager;
      private FragmentTransaction currentTransaction;
    
    
      public CustomPagerAdapter(FragmentManager fragmentManager) {
        this.fragmentManager = fragmentManager;
      }
    
      @Override
      public Object instantiateItem(ViewGroup container, int position) {
        if (currentTransaction == null) {
          currentTransaction = fragmentManager.beginTransaction();
        }
    
        Fragment pageFragment = pages.get(position);
        String tag = pageFragment.getArguments().getString(MainActivity.FRAGMENT_TAG_ARG);
        Fragment fragment = fragmentManager.findFragmentByTag(tag);
    
        if (fragment != null) {
          if (fragment.getId() == container.getId()) {
            currentTransaction.attach(fragment);
          }
          else {
            fragmentManager.beginTransaction().remove(fragment).commit();
            fragmentManager.executePendingTransactions();
            currentTransaction.add(container.getId(), fragment, tag);
          }
        }
        else {
          fragment = pageFragment;
          currentTransaction.add(container.getId(), fragment, tag);
        }
    
        if (fragment != currentPrimaryItem) {
          fragment.setMenuVisibility(false);
          fragment.setUserVisibleHint(false);
        }
    
        return fragment;
      }
    
      @Override
      public int getCount() {
        return pages.size();
      }
    
      @Override
      public void destroyItem(ViewGroup container, int position, Object object) {
        if (currentTransaction == null) {
          currentTransaction = fragmentManager.beginTransaction();
        }
    
        currentTransaction.detach((Fragment) object);
      }
    
      @Override
      public void setPrimaryItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment) object;
    
        if (fragment != currentPrimaryItem) {
          if (currentPrimaryItem != null) {
            currentPrimaryItem.setMenuVisibility(false);
            currentPrimaryItem.setUserVisibleHint(false);
          }
    
          if (fragment != null) {
            fragment.setMenuVisibility(true);
            fragment.setUserVisibleHint(true);
          }
    
          currentPrimaryItem = fragment;
        }
      }
    
      @Override
      public void finishUpdate(ViewGroup container) {
        if (currentTransaction != null) {
          currentTransaction.commitAllowingStateLoss();
          currentTransaction = null;
          fragmentManager.executePendingTransactions();
        }
      }
    
      @Override
      public boolean isViewFromObject(View view, Object object) {
        return ((Fragment) object).getView() == view;
      }
    
      @Override
      public int getItemPosition(Object o) {
        Integer result = fragmentsPosition.get(o);
    
        if (result == null) {
          return PagerAdapter.POSITION_UNCHANGED;
        }
    
        return result;
      }
    
      // ---------------------------------- Page actions ----------------------------------
    
      public void addPage(Fragment fragment) {
        fragmentsPosition.clear();
        pages.add(fragment);
        notifyDataSetChanged();
      }
    
      public void removePage(int position) {
        fragmentsPosition.clear();
    
        Fragment pageFragment = pages.get(position);
        String tag = pageFragment.getArguments().getString(MainActivity.FRAGMENT_TAG_ARG);
    
        Fragment fragment = fragmentManager.findFragmentByTag(tag);
    
        if (fragment != null) {
          fragmentsPosition.put(fragment, PagerAdapter.POSITION_NONE);
        }
    
        for (int i = position + 1; i < pages.size(); i++) {
          pageFragment = pages.get(i);
          tag = pageFragment.getArguments().getString(MainActivity.FRAGMENT_TAG_ARG);
          fragment = fragmentManager.findFragmentByTag(tag);
    
          if (fragment != null) {
            fragmentsPosition.put(fragment, i - 1);
          }
        }
    
        pages.remove(position);
        notifyDataSetChanged();
      }
    
    }
    

    MainActivity:

    import android.os.Bundle;
    import android.support.v4.view.ViewPager;
    import android.support.v7.app.AppCompatActivity;
    
    public class MainActivity extends AppCompatActivity {
    
      public static final String FRAGMENT_TAG_ARG = "tag";
    
      private CustomPagerAdapter mCustomPagerAdapter;
    
      private ViewPager mViewPager;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mCustomPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager());
        mCustomPagerAdapter.addPage(MainFragment.newInstance("Main_Title"));
        mCustomPagerAdapter.addPage(SecondaryFragment.newInstance("Secondary_Title"));
    
        mViewPager = (ViewPager) findViewById(R.id.container);
        mViewPager.setAdapter(mCustomPagerAdapter);
      }
    
    }
    

    To remove pages:

    mCustomPagerAdapter.removePage(1);
    

    MainFragment:

    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    public class MainFragment extends Fragment {
    
      public static final String FRAGMENT_TAG = "MainFragment";
    
      public static MainFragment newInstance(String text) {
        return newInstance(text, FRAGMENT_TAG);
      }
    
      public static MainFragment newInstance(String text, String tag) {
        MainFragment fragment = new MainFragment();
        Bundle args = new Bundle();
        args.putString("text", text);
        args.putString(MainActivity.FRAGMENT_TAG_ARG, tag + "_" + fragment.hashCode());
        fragment.setArguments(args);
        return fragment;
      }
    
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);
        TextView textView = (TextView) rootView.findViewById(R.id.section_label);
        textView.setText(getArguments().getString("text"));
        return rootView;
      }
    
    }
    

    SecondaryFragment has the same code.

    The layouts are simple ViewPager/Fragment layouts with android.support.v4.view.ViewPager with id container and Fragment TextView with id section_label.

    Resources:

    • dynamically add and remove view to viewpager
    • How to Remove Fragment from FragmentPagerAdapter?
    • https://github.com/takaaki7/ArrayPagerAdapter
    • https://github.com/commonsguy/cwac-pager
    0 讨论(0)
  • 2021-01-30 00:04

    Yes, since ViewPager gets the child Views from a PagerAdapter, you can add new pages / delete pages on that, and call .notifyDataSetChanged() to reload it.

    0 讨论(0)
  • 2021-01-30 00:09

    Yes, the code should be like this:

    public int addPage(View view, int position) {
            if ((position >= 0) && (position < getSize())) {
                myPagerAdapter.mListViews.add(position, view);
                myPagerAdapter.notifyDataSetChanged();
                return position;
            } else {
                return -1;
            }
        }
    
    public View removePage(int position) {
            if ((position < 0) || (position >= getSize()) || (getSize()<=1)) {
                return null;
            } else {
                if (position == mPager.getCurrentItem()) {
                    if(position == (getSize()-1)) {
                        mPager.setCurrentItem(position-1);
                    } else if (position == 0){
                        mPager.setCurrentItem(1);
                    }
                }
                View tempView = myPagerAdapter.mListViews.remove(position);
                myPagerAdapter.notifyDataSetChanged();
                return tempView;
            }
        }
    

    But there is a bug. If the current Item is 0, and to remove page 0, it will not refresh the screen instantly, I haven't found a solution for this.

    0 讨论(0)
  • 2021-01-30 00:13

    First:override the pagerAdapter method "getItemPosition"

    @Override
    public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    }
    

    Second:remove the data bind with the adapter.and call adapter.notifydatachanged

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