Dynamically remove item from ViewPager using FragmentStatePagerAdapter

This topic discusses quite a lot of discussions.

I tried various solutions (including invalidation with POSITION_NONE ), but I still don’t know how to delete the item correctly.

What's going on is

  • or I get a blank page (this means the fragment is destroyed, but instantiateItem not called for replacement)
  • or all this happens, probably due to the fact that Android controls the fragments do not match the way I store them in my arraylist/sparsearray

Here is my adapter

 private class DatePickerPagerAdapter extends FragmentStatePagerAdapter { ArrayList<Fragment> registeredFragments = new ArrayList<Fragment>(); public DatePickerPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return CreateWishFormDatePaginationFragment.newInstance(position); } @Override public int getItemPosition(Object object){ //doesnt change much.. return PagerAdapter.POSITION_NONE; } @Override public int getCount() { return iPageCount; } @Override public Object instantiateItem(ViewGroup container, int position) { Fragment fragment = (Fragment) super.instantiateItem(container, position); registeredFragments.add(position, fragment); return fragment; } @Override public void destroyItem(ViewGroup container, int position, Object object) { super.destroyItem(container, position, registeredFragments.get(position)); } public void removePage(ViewGroup pager, int position) { destroyItem(pager, position, null); registeredFragments.remove(position); iPageCount--; pagerIndicator.notifyDataSetChanged(); pagerAdapter.notifyDataSetChanged(); } public void addPage() { iPageCount++; pagerIndicator.notifyDataSetChanged(); pagerAdapter.notifyDataSetChanged(); } } 

I am using a view pager with a ViewPagerIndicator, and I want, for example, to delete a page between them.

Therefore, the question remains: What is the correct way to handle addition and deletion of fragments in the ViewPager?

Thanks!

+6
source share
2 answers

If you want to remove items from the ViewPager , this following code does not make sense:

 @Override public Fragment getItem(int position) { return CreateWishFormDatePaginationFragment.newInstance(position); } 

Essentially, you create a Fragment based on position . No matter which page you delete, the range of position will change from [0, iPageCount ) to [0, iPageCount-1 ) , which means that it will always be rid of the last Fragment .


What you need is more or less the following:

 public class DatePickerPagerAdapter extends FragmentStatePagerAdapter { private ArrayList<Integer> pageIndexes; public DatePickerPagerAdapter(FragmentManager fm) { super(fm); pageIndexes = new ArrayList<>(); for (int i = 0; i < 10; i++) { pageIndexes.add(new Integer(i)); } } @Override public int getCount() { return pageIndexes.size(); } @Override public Fragment getItem(int position) { Integer index = pageIndexes.get(position); return CreateWishFormDatePaginationFragment.newInstance(index.intValue()); } // This is called when notifyDataSetChanged() is called @Override public int getItemPosition(Object object) { // refresh all fragments when data set changed return PagerAdapter.POSITION_NONE; } // Delete a page at a `position` public void deletePage(int position) { // Remove the corresponding item in the data set pageIndexes.remove(position); // Notify the adapter that the data set is changed notifyDataSetChanged(); } } 

For more information on removing an item from the FragmentStatePagerAdapter, see the full example .

+13
source

The ViewPager does not delete your fragments using the code above, since it loads several views (or fragments in your case) into memory. In addition to the visible view, it also loads the view in either direction of the visible. This ensures smooth scrolling from view to view, which makes ViewPager so cool.

To achieve the desired effect, you need to do a couple of things.

Change the FragmentPagerAdapter to FragmentStatePagerAdapter. The reason for this is because the FragmentPagerAdapter will save all the views that it loads into memory forever. If the FragmentStatePagerAdapter has views that go beyond the current and view views. Override the adapter method getItemPosition (shown below). When we call mAdapter.notifyDataSetChanged (); ViewPager requests an adapter to determine what has changed in terms of positioning. We use this method to say that everything has changed, so rework all your positioning. And here is the code ...

 private class MyPagerAdapter extends FragmentStatePagerAdapter { //... your existing code @Override public int getItemPosition(Object object){ return PagerAdapter.POSITION_NONE; } } 
+2
source

Source: https://habr.com/ru/post/981440/


All Articles