insert and remove fragments into viewpager properly

前端 未结 3 997
旧时难觅i
旧时难觅i 2021-02-03 12:02

I\'m making an adroid application with viewpager and fragments. I want to make an option to add or remove fragment pages to the pager dynamically. I have a custom FragmentPagerA

3条回答
  •  盖世英雄少女心
    2021-02-03 12:50

    This is what I used to get around the problem with fragments being tagged when instantiated and the fact that previously tagged fragments cannot change position within the ViewPager when trying to add or remove pages, i.e. getting the exception:

    java.lang.IllegalStateException: Can't change tag of fragment MyFragment{4055f558 id=0x7f050034 android:switcher:2131034164:3}: was android:switcher:2131034164:3 now android:switcher:2131034164:4

    This adapter is created with a list of all pages upfront and you can then use setEnabled(int position, boolean enabled) to disable or enable certain pages which hides or shows these pages in the ViewPager.

    It works by maintaining an internal list of all fragments but exposing to the ViewPager and mapping the positions of enabled fragments only.

    public class DynamicFragmentPagerAdapter extends FragmentPagerAdapter {
    
        public final ArrayList screens = new ArrayList();
    
        private Context context;
        private List flags = new ArrayList();
    
        public DynamicFragmentPagerAdapter(FragmentManager fm, Context context, List> screens) {
            super(fm);
            this.context = context;
    
            for(Class screen : screens)
                addScreen(screen, null);
    
            notifyDataSetChanged();
        }
    
        public DynamicFragmentPagerAdapter(FragmentManager fm, Context context, Map, Bundle> screens) {
            super(fm);
            this.context = context;
    
            for(Class screen : screens.keySet())
                addScreen(screen, screens.get(screen));
    
            notifyDataSetChanged();
        }
    
        private void addScreen(Class clazz, Bundle args) {
            screens.add(Fragment.instantiate(context, clazz.getName(), args));
            flags.add(new AtomicBoolean(true));
        }
    
        public boolean isEnabled(int position) {
            return flags.get(position).get();
        }
    
        public void setEnabled(int position, boolean enabled) {
            AtomicBoolean flag = flags.get(position);
            if(flag.get() != enabled) {
                flag.set(enabled);
                notifyDataSetChanged();
            }
        }
    
        @Override
        public int getCount() {
            int n = 0;
            for(AtomicBoolean flag : flags) {
                if(flag.get())
                    n++;
            }
            return n;
        }
    
        @Override
        public Fragment getItem(int position) {
            return screens.get(position);
        }
    
        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE; // To make notifyDataSetChanged() do something
        }
    
        @Override
        public void notifyDataSetChanged() {
            try {
                super.notifyDataSetChanged();
            } catch (Exception e) {
                Log.w("", e);
            }
        }
    
        private List getEnabledScreens() {
            List res = new ArrayList();
            for(int n = 0; n < screens.size(); n++) {
                if(flags.get(n).get())
                    res.add(screens.get(n));
            }
            return res;
        }
    
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            // We map the requested position to the position as per our screens array list
            Fragment fragment = getEnabledScreens().get(position);
            int internalPosition = screens.indexOf(fragment);
            return super.instantiateItem(container, internalPosition);
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            Fragment fragment = getEnabledScreens().get(position);
            if(fragment instanceof TitledFragment)
                return ((TitledFragment)fragment).getTitle(context);
            return super.getPageTitle(position);
        }
    
        public static interface TitledFragment {
            public String getTitle(Context context);
        }
    }
    

提交回复
热议问题