Update ViewPager dynamically?

后端 未结 20 3083
时光说笑
时光说笑 2020-11-22 02:00

I can\'t update the content in ViewPager.

What is the correct usage of methods instantiateItem() and getItem() in FragmentPagerAdapter class?

I was using onl

相关标签:
20条回答
  • 2020-11-22 02:17

    This solution won't work for everyone, but in my case, every Fragment in my ViewPager is a different class, and only one of them ever exist at a time.

    With this constraint, this solution is safe and should be safe to use in production.

    private void updateFragment(Item item) {
    
        List<Fragment> fragments = getSupportFragmentManager().getFragments();
        for (Fragment fragment : fragments) {
    
            if (fragment instanceof MyItemFragment && fragment.isVisible()) {
                ((MyItemFragment) fragment).update(item);
            }
    
        }
    }
    

    If you have multiple versions of the same fragment, you can use this same strategy to call methods on those fragments to determine if it is the fragment you wish to update.

    0 讨论(0)
  • 2020-11-22 02:18

    I slightly modified the solution provided by Bill Phillips to suit my needs

    private class PagerAdapter extends FragmentStatePagerAdapter{
        Bundle oBundle;
        FragmentManager oFragmentManager;
        ArrayList<Fragment> oPooledFragments;
    
    public PagerAdapter(FragmentManager fm) {
        super(fm);
        oFragmentManager=fm;
    
        }
    @Override
    public int getItemPosition(Object object) {
    
        Fragment oFragment=(Fragment)object;
        oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
        if(oPooledFragments.contains(oFragment))
            return POSITION_NONE;
        else
            return POSITION_UNCHANGED;
        } 
    }
    

    so that the getItemPosition() returns POSITION_NONE only for those fragments which are currently in the FragmentManager when getItemPosition is called. (Note that this FragmentStatePager and the ViewPager associated with it are contained in a Fragment not in a Activity)

    0 讨论(0)
  • 2020-11-22 02:24

    If you want to use FragmentStatePagerAdapter, please take a look at https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=37990. There are issues with FragmentStatePagerAdapter that may or may not trouble your use case.

    Also, link has few solutions too..few may suit to your requirement.

    0 讨论(0)
  • 2020-11-22 02:30

    After hours of frustration while trying all the above solutions to overcome this problem and also trying many solutions on other similar questions like this, this and this which all FAILED with me to solve this problem and to make the ViewPager to destroy the old Fragment and fill the pager with the new Fragments. I have solved the problem as following:

    1) Make the ViewPager class to extends FragmentPagerAdapter as following:

     public class myPagerAdapter extends FragmentPagerAdapter {
    

    2) Create an Item for the ViewPager that store the title and the fragment as following:

    public class PagerItem {
    private String mTitle;
    private Fragment mFragment;
    
    
    public PagerItem(String mTitle, Fragment mFragment) {
        this.mTitle = mTitle;
        this.mFragment = mFragment;
    }
    public String getTitle() {
        return mTitle;
    }
    public Fragment getFragment() {
        return mFragment;
    }
    public void setTitle(String mTitle) {
        this.mTitle = mTitle;
    }
    
    public void setFragment(Fragment mFragment) {
        this.mFragment = mFragment;
    }
    
    }
    

    3) Make the constructor of the ViewPager take my FragmentManager instance to store it in my class as following:

    private FragmentManager mFragmentManager;
    private ArrayList<PagerItem> mPagerItems;
    
    public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
        super(fragmentManager);
        mFragmentManager = fragmentManager;
        mPagerItems = pagerItems;
    }
    

    4) Create a method to re-set the adapter data with the new data by deleting all the previous fragment from the fragmentManager itself directly to make the adapter to set the new fragment from the new list again as following:

    public void setPagerItems(ArrayList<PagerItem> pagerItems) {
        if (mPagerItems != null)
            for (int i = 0; i < mPagerItems.size(); i++) {
                mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
            }
        mPagerItems = pagerItems;
    }
    

    5) From the container Activity or Fragment do not re-initialize the adapter with the new data. Set the new data through the method setPagerItems with the new data as following:

    ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
        pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
        pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));
    
        mPagerAdapter.setPagerItems(pagerItems);
        mPagerAdapter.notifyDataSetChanged();
    

    I hope it helps.

    0 讨论(0)
  • 2020-11-22 02:31

    You need change instantiateItem's mFragments element getItemPosition.

        if (mFragments.size() > position) {
            Fragment f = mFragments.get(position);
    
            if (f != null) {
                int newPosition = getItemPosition(f);
                if (newPosition == POSITION_UNCHANGED) {
                    return f;
                } else if (newPosition == POSITION_NONE) {
                    mFragments.set(position, null);
                } else {
                    mFragments.set(newPosition, f);
                }
            }
        }
    

    Based AndroidX FragmentStatePagerAdapter.java, because mFragments's elements position do not change when calling notifyDataSetChanged().

    Source: https://github.com/cuichanghao/infivt/blob/master/library/src/main/java/cc/cuichanghao/library/FragmentStatePagerChangeableAdapter.java

    Example: https://github.com/cuichanghao/infivt/blob/master/app/src/main/java/cc/cuichanghao/infivt/MainActivityChangeablePager.kt

    You can run this project to confirm how to work. https://github.com/cuichanghao/infivt

    0 讨论(0)
  • 2020-11-22 02:32

    I had been trying so many different approaches, none really sove my problem. Below are how I solve it with a mix of solutions provided by you all. Thanks everyone.

    class PagerAdapter extends FragmentPagerAdapter {
    
        public boolean flag_refresh=false;
    
        public PagerAdapter(FragmentManager fm) {
            super(fm);
        }
    
        @Override
        public Fragment getItem(int page) {
            FragmentsMain f;
            f=new FragmentsMain();
            f.page=page;
            return f;
        }
    
        @Override
        public int getCount() {
            return 4;
        }
    
        @Override
        public int getItemPosition(Object item) {
            int page= ((FragmentsMain)item).page;
    
            if (page == 0 && flag_refresh) {
                flag_refresh=false;
                return POSITION_NONE;
            } else {
                return super.getItemPosition(item);
            }
        }
    
        @Override
        public void destroyItem(View container, int position, Object object) {
    
            ((ViewPager) container).removeView((View) object);
        }
    }
    

    I only want to refresh page 0 after onResume().

     adapter=new PagerAdapter(getSupportFragmentManager());
     pager.setAdapter(adapter);
    
    @Override
    protected void onResume() {
        super.onResume();
    
        if (adapter!=null) {
            adapter.flag_refresh=true;
            adapter.notifyDataSetChanged();
        }
    }
    

    In my FragmentsMain, there is public integer "page", which can tell me whether it is the page I want to refresh.

    public class FragmentsMain extends Fragment {
    
    private Cursor cursor;
    private static Context context;
    public int page=-1;
    
    0 讨论(0)
提交回复
热议问题