Search code examples
androidandroid-fragmentsandroid-viewpagerandroid-adapter

Dynamically remove an item from a ViewPager with FragmentStatePagerAdapter


There are quite a few discussions around this topic

I have tried various solutions (including the invalidation with POSITION_NONE) . But I still donT know how to remove an item properly.

What happens is

  • either I get a blank page (meaning the fragment is destroyed, but the instantiateItem was not called for a replacement)
  • or the whole thing crashes probably because the way the Android manages the fragment instances do not match how I keep them in my arraylist/sparsearray

Here s 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 ViewPagerIndicator and I want to be able to remove a page in between, for example.

Hence remains the question, what is the proper way handling addition and removal of fragments in a ViewPager?

Thanks!


Solution

  • If you want to remove items from a 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 the position. No matter which page you remove, the range of the position will change from [0, iPageCount) to [0, iPageCount-1), which means that it will always get 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();
        }
    }
    

    Please refer to this complete example for more details about removing item from FragmentStatePagerAdapter.