安卓ViewPager更改适配器

18

我正在开发一个使用ViewPager实现横向滚动表格的应用程序,有时需要更改适配器以加载不同的表格集合。我尝试了以下方法:

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

但它总是重新加载上一个数据。更改ViewPager的适配器不可能吗?

6个回答

34

就像我的应用程序所做的一样...

要更改ViewPagerAdapter,我所做的是:

  1. 清除当前适配器中的所有片段

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

  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);

希望这有所帮助~


3
我尝试了你的解决方案,它完美地运行,没有任何问题。非常感谢。 - Leo Nguyen
在API 18中,我无法使用setAdapter(null)。但是其他所有功能都可以正常工作。谢谢。 - ffleandro
非常感谢!我已经寻找这个东西好几天了! - Antiohia
1
对我来说,唯一必要的部分是使用片段管理器事务删除片段。其余部分都是不必要的(例如:removeAllViews、setAdapter(null)等)。 - Grant Amos
7
由于某些原因,只有在我将它从FragmentPagerAdapter更改为FragmentStatePagerAdapter后才能使其正常工作。 - Sree

3
你需要在pager适配器中重写public int getItemPosition (Object object)方法。对于viewpager中的每个元素,你需要返回POSITION_UNCHANGED(如果它仍然在pager中)或POSITION_NONE(如果它被移除了)。否则,view pager将不知道有些内容已经被更改。我不建议设置一个新的适配器,只需清空旧适配器中的数据即可。

3

我看到@RRTW的方法对一些人有效,但对我并没有起作用(虽然接近)。如果不使用commit()而是使用commitNow(),它将无法正常工作。我做了类似这样的事情:

private fun changePagerAdapter(newAdapter: PagerAdapter) {

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

    transaction.commitNow()
    view_pager.adapter = newAdapter
}

0
对于那些仍然遇到问题的人,可以像我一样做。希望这能节省你的时间。这是在Xamarin.Android中,但是在Java和Kotlin中的思路应该是相同的。
通过抽象类准备您的适配器类,并使用ClearFragments方法:
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)
    {
        
    }
}

当您想要更改适配器时,请按照以下步骤操作:

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();
    }
}

0

-5

将以下代码添加到视图分页器中,以便为下一个片段重新加载:

viewPager.setCurrentItem()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接