18

我正在为横向滚动表开发一个带有 ViewPager 的应用程序,有时我需要更改适配器以加载一组不同的表。我尝试执行以下操作:

mViewPager.setAdapter(new pagerAdapterPushed(getSupportFragmentManager()));
mViewPager.getAdapter().notifyDataSetChanged();
indicator.setViewPager(mViewPager);
indicator.invalidate();
mViewPager.invalidate();

但它总是重新加载以前的数据。是不是可以更改 ViewPager 的适配器?

4

6 回答 6

34

就像我的APP做的一样...

对于更改 ViewPagerAdapter,我所做的是:

  1. 清除当前适配器内的所有 Fragment

  2. 将当前适配器设置为空

  3. 为 ViewPager 分配新的适配器

    /* Clear all Fragments inside current adapter */
    public class MyPagerAdapter extends FragmentPagerAdapter
    {
      private ArrayList<Fragment> fragments = new ArrayList<Fragment>();
      //...some stuff
    
      public void clearAll() //Clear all page
      {
        for(int i = 0; i < fragments.size(); i ++)
        fragMan.beginTransaction().remove(fragments.get(i)).commit();
        fragments.clear();
      }
    }
    
    /* Set current adapter to null */
    Constants.VP.removeAllViews();
    Constants.VP.setAdapter(null);
    
    /* Assign new adpater for ViewPager */
    Constants.PAGER = new MyPagerAdapter(getSupportFragmentManager());
    Constants.VP.setAdapter(Constants.PAGER);
    

希望有帮助~

于 2013-04-11T09:18:00.913 回答
3

您需要public int getItemPosition (Object object)在寻呼机适配器中覆盖。对于视图分页器中的每个元素,您需要返回POSITION_UNCHANGED(如果它仍在分页器中)或POSITION_NONE(如果它已被删除)。否则视图寻呼机将不知道发生了什么变化。我不建议设置新适配器,只需清除旧适配器中的数据即可。

于 2013-02-12T05:37:04.070 回答
2

我看到@RRTW 方式对某些人有用,但对我没有用(尽管它很接近)。如果没有commitNow()代替常规commit(),它将无法正常工作。我做了这样的事情:

private fun changePagerAdapter(newAdapter: PagerAdapter) {

    val transaction = supportFragmentManager.beginTransaction()
        supportFragmentManager.fragments.forEach {
        transaction.remove(it)
    }

    transaction.commitNow()
    view_pager.adapter = newAdapter
}
于 2018-07-13T06:17:03.667 回答
0

For those who still have issues, do like what I did. I wish it will save your time. It is in Xamarin.Android, but idea should be same in java and kotlin

Prepare your Adapter classes with ClearFragments method through an abstract class:

public abstract class BaseAdapter : FragmentStateAdapter
{
    public BaseAdapter(FragmentManager fm, Lifecycle lifecycle) : base(fm, lifecycle)
    {
        this.fm = fm;
    }
    readonly FragmentManager fm;
    
    public override int ItemCount => ITEM_COUNT;

    private readonly List<Fragment> fragments = new List<Fragment>();
    
    
    public override Fragment CreateFragment(int position)
    {
        var fragment = new MyFragment();
        fragments.Add(fragment);
        return fragment;
    }
    
    public void ClearFragments()
    {
        if (fragments.Count > 0)
        {
            var transaction = fm.BeginTransaction();
            foreach (var fragment in fragments)
            {
                transaction.Remove(fragment);
            }
            if (!fm.IsDestroyed)
            {
                transaction.CommitNow();
            }
            //see note of Dispose(disposing)
            foreach (var fragment in fragments)
            {
                fragment.Dispose();
            }
            fragments.Clear();
        }
    }
    
    private bool disposedValue = false;
    
    //Important note: Your fragment might use Context. You need to override Dispose(disposing) in your fragment class
    //and ensure you do not use Context after you dispose it here
    protected override void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            disposedValue = true;
            if (disposing)
            {
                ClearFragments();
            }
            base.Dispose(disposing);
        }
    }
}

public Adapter1 : BaseAdapter
{
    public Adapter1(FragmentManager fm, Lifecycle lifecycle) : base(fm, lifecycle)
    {
        
    }
}

public Adapter2 : BaseAdapter
{
    public Adapter2(FragmentManager fm, Lifecycle lifecycle) : base(fm, lifecycle)
    {
        
    }
}

Then when you want to change adapter, do like this:

public MainActivity : AppCompatActivity
{
    private void UseAdapter2()
    {
        var oldAdapter = viewPager.Adapter as BaseAdapter;
        oldAdapter?.ClearFragments();
        viewPager.Adapter = null;
        var adapter = new Adapter2(SupportFragmentManager, Lifecycle);
        // Do any logic that makes this adapter different from the previous one.
        viewPager.Adapter = adapter;
        oldAdapter?.Dispose();
    }
}
于 2021-07-31T21:32:58.620 回答
0

@ibrahim 您的建议与 ViewPager2 文档的建议背道而驰。它特别声明不要将该技术用于 CreateFragment。您必须始终返回片段的新实例。不要从片段列表中重复使用。见https://developer.android.com/training/animation/vp2-migration

于 2021-08-01T00:47:28.327 回答
-5

将此添加到查看寻呼机以重新加载下一个片段:

viewPager.setCurrentItem()
于 2015-02-27T05:30:01.127 回答