331

我无法更新 ViewPager 中的内容。

FragmentPagerAdapter 类中方法 instantiateItem() 和 getItem() 的正确用法是什么?

我只使用 getItem() 来实例化并返回我的片段:

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

这运作良好。除了我不能改变内容。

所以我发现了这个:ViewPager PagerAdapter not updates the View

“我的方法是对 instanceItem() 方法中的任何实例化视图使用 setTag() 方法”

现在我想实现 instantiateItem() 来做到这一点。但我不知道我必须返回什么(类型是 Object)以及与 getItem(int position) 的关系是什么?

我阅读了参考资料

  • 公共抽象片段 getItem(int 位置)

    返回与指定位置关联的 Fragment。

  • public Object instantiateItem(ViewGroup 容器,int 位置)

    为给定位置创建页面。适配器负责将视图添加到此处给出的容器中,尽管它只必须确保在它从 finishUpdate(ViewGroup) 返回时完成此操作。参数

    容器 将在其中显示页面的包含视图。position 要实例化的页面位置。

    退货

    返回一个表示新页面的对象。这不需要是视图,但可以是页面的其他容器。

但我还是不明白。

这是我的代码。我正在使用支持包 v4。

ViewPagerTest

public class ViewPagerTest extends FragmentActivity {
    private ViewPager pager;
    private MyFragmentAdapter adapter; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pager1);

        pager = (ViewPager)findViewById(R.id.slider);

        String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};

        adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        pager.setAdapter(adapter);

        ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });
    }

    private void reload() {
        String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
        //adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        adapter.setData(data);
        adapter.notifyDataSetChanged();
        pager.invalidate();

        //pager.setCurrentItem(0);
    }
}

我的片段适配器

class MyFragmentAdapter extends FragmentPagerAdapter {
    private int slideCount;
    private Context context;
    private String[] data;

    public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
        super(fm);
        this.slideCount = slideCount;
        this.context = context;
        this.data = data;
    }

    @Override
    public Fragment getItem(int position) {
        return new MyFragment(data[position], context);
    }

    @Override
    public int getCount() {
        return slideCount;
    }

    public void setData(String[] data) {
        this.data = data;
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}

我的片段

public final class MyFragment extends Fragment {
    private String text;

    public MyFragment(String text, Context context) {
        this.text = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide, null);
        ((TextView)view.findViewById(R.id.text)).setText(text);

        return view;
    }
}

这里也有人有类似问题,没有答案 http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html

4

21 回答 21

622

在使用 FragmentPagerAdapter 或 FragmentStatePagerAdapter 时,最好单独处理,完全getItem()不接触instantiateItem()。PagerAdapter 上的instantiateItem()- destroyItem()-isViewFromObject()接口是一个较低级别的接口,FragmentPagerAdapter 使用它来实现更简单的getItem()接口。

在进入这个之前,我应该澄清一下

如果要切换出正在显示的实际片段,则需要避免使用 FragmentPagerAdapter 并使用 FragmentStatePagerAdapter。

此答案的早期版本错误地将 FragmentPagerAdapter 用作其示例 - 这将不起作用,因为 FragmentPagerAdapter 在第一次显示后永远不会破坏片段。

我不推荐您链接的帖子中提供的解决方法setTag()findViewWithTag()正如您所发现的,使用setTag()findViewWithTag()不适用于片段,所以它不是一个很好的匹配。

正确的解决方案是覆盖getItemPosition(). 当notifyDataSetChanged()被调用时,ViewPager 会调用getItemPosition()其适配器中的所有项目,以查看它们是否需要移动到不同的位置或移除。

默认情况下,getItemPosition()返回POSITION_UNCHANGED,这意味着,“这个对象在它所在的地方很好,不要破坏或删除它。” 返回POSITION_NONE解决了这个问题,而是说,“这个对象不再是我正在显示的项目,删除它。” 因此,它具有删除和重新创建适配器中每个项目的效果。

这是一个完全合法的修复!此修复使 notifyDataSetChanged 的​​行为类似于常规适配器,无需视图回收。如果您实施此修复并且性能令人满意,那么您就可以参加比赛了。任务完成。

如果您需要更好的性能,您可以使用更高级的getItemPosition()实现。这是一个寻呼机从字符串列表中创建片段的示例:

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
    public int getCount() {
        return titles.size();
    }

    public Fragment getItem(int position) {
        MyFragment fragment = new MyFragment();
        fragment.setTitle(titles.get(position));
        return fragment;
    }

    public int getItemPosition(Object item) {
        MyFragment fragment = (MyFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }
});

使用此实现,只会显示显示新标题的片段。任何显示仍在列表中的标题的片段都将被移动到它们在列表中的新位置,并且标题不再在列表中的片段将被销毁。

如果片段尚未重新创建,但仍需要更新怎么办?对活动片段的更新最好由片段本身处理。毕竟,这就是拥有片段的优势——它是它自己的控制器。片段可以在 中向另一个对象添加侦听器或观察者onCreate(),然后在 中删除它onDestroy(),从而自行管理更新。您不必getItem()像在 ListView 或其他 AdapterView 类型的适配器中那样将所有更新代码放入其中。

最后一件事——仅仅因为 FragmentPagerAdapter 不破坏片段并不意味着 getItemPosition 在 FragmentPagerAdapter 中完全没用。您仍然可以使用此回调在 ViewPager 中重新排序您的片段。但是,它永远不会将它们完全从 FragmentManager 中删除。

于 2012-06-01T14:22:07.693 回答
149

不要从返回POSITION_NONEgetItemPosition()引起全视图娱乐,而是这样做:

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(updateData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

您的片段应该实现UpdateableFragment接口:

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

和界面:

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

您的数据类:

public class UpdateData {
    //whatever you want here
}
于 2013-07-25T10:40:15.743 回答
27

对于那些仍然面临我之前遇到的相同问题的人,当我有ViewPager7 个片段时。这些片段的默认设置是从API服务中加载英语内容,但这里的问题是我想从设置活动中更改语言,并且在完成设置活动后,我希望ViewPager在主要活动中刷新片段以匹配用户的语言选择并加载如果用户在这里选择阿拉伯语,则阿拉伯语内容我从第一次开始工作

1-您必须使用上面提到的 FragmentStatePagerAdapter。

2- 在 mainActivity 我覆盖 onResume 并做了以下

if (!(mPagerAdapter == null)) {
    mPagerAdapter.notifyDataSetChanged();
}

3-i 覆盖了getItemPosition()mPagerAdapter 并使其返回POSITION_NONE

@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}

像魅力一样工作

于 2014-12-11T11:40:33.487 回答
16
于 2013-08-08T06:51:35.653 回答
13

在您的代码中尝试destroyDrawingCache()ViewPager 。notifyDataSetChanged()

于 2013-07-09T09:03:34.290 回答
11

经过数小时的挫折,同时尝试了所有上述解决方案来克服这个问题,并尝试了许多其他类似问题的解决方案,比如这个这个这个都失败了,我无法解决这个问题并ViewPager破坏旧的并Fragment填充pagerFragments。我已经解决了以下问题:

1)使ViewPager类扩展FragmentPagerAdapter如下:

 public class myPagerAdapter extends FragmentPagerAdapter {

2)ViewPager为该商店创建一个项目,title如下fragment所示:

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)使ViewPagertake myFragmentManager实例的构造函数将其存储在myclass中,如下所示:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

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

4)创建一个方法来用新数据重新设置adapter数据,方法是直接fragmentfragmentManager自身中删除所有以前的数据,以便再次从新列表adapter中设置新数据fragment,如下所示:

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)从容器ActivityFragment不使用新数据重新初始化适配器。通过使用新数据的方法设置setPagerItems新数据如下:

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

我希望它有所帮助。

于 2014-03-08T18:03:07.333 回答
9

For some reason none of the answers worked for me so I had to override the restoreState method without calling super in my fragmentStatePagerAdapter. Code:

private class MyAdapter extends FragmentStatePagerAdapter {

    // [Rest of implementation]

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {}

}
于 2015-08-18T15:41:47.827 回答
3

我稍微修改了比尔菲利普斯提供的解决方案以满足我的需要

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

以便仅getItemPosition()返回当前在whenPOSITION_NONE中的那些片段。(请注意,此及其关联的内容包含在 Fragment 中而不是 Activity 中)FragmentManagergetItemPositionFragmentStatePagerViewPager

于 2014-04-23T13:23:08.083 回答
2

我有一个类似的问题,但不想相信现有的解决方案(硬编码标签名称等),我无法让 M-WaJeEh 的解决方案为我工作。这是我的解决方案:

我将在 getItem 中创建的片段的引用保存在一个数组中。只要活动没有因配置更改或内存不足或其他原因而被破坏(-->返回活动时,片段返回到它们的最后状态而不会再次调用“getItem”,因此不会更新数组,这工作正常)。

为了避免这个问题,我实现了 instantiateItem(ViewGroup, int) 并在那里更新我的数组,如下所示:

        @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object o = super.instantiateItem(container, position);
        if(o instanceof FragmentX){
            myFragments[0] = (FragmentX)o;
        }else if(o instanceof FragmentY){
            myFragments[1] = (FragmentY)o;
        }else if(o instanceof FragmentZ){
            myFragments[2] = (FragmentZ)o;
        }
        return o;
    }

所以,一方面我很高兴我找到了一个适合我的解决方案并想与你分享,但我也想问是否有人尝试过类似的东西,是否有任何理由我不应该这样做吗?到目前为止,它对我来说非常好......

于 2013-11-06T12:00:56.217 回答
2

我也遇到过同样的问题,而且我搜索了太多次。在 stackoverflow 或通过谷歌给出的任何答案都不能解决我的问题。我的问题很简单。我有一个列表,我用 viewpager 显示这个列表。当我将一个新元素添加到列表的头部并刷新 viewpager 时,什么都没有改变。我的最终解决方案非常简单,任何人都可以使用。当一个新元素添加到列表中并且想要刷新列表时。首先将 viewpager 适配器设置为 null 然后重新创建适配器并将 i 设置为 viewpager。

myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);

确保您的适配器必须扩展 FragmentStatePagerAdapter

于 2017-08-07T09:10:10.727 回答
1

我使用EventBus库来更新Fragment. ViewPager逻辑很简单,就像EventBus 怎么做的文档。无需控制FragmentPagerAdapter实例。代码在这里:

1:定义事件

定义需要更新的消息。

public class UpdateCountEvent {
    public final int count;

    public UpdateCountEvent(int count) {
        this.count = count;
    }
}

2.准备订阅者

在需要更新的片段中写入以下代码。

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);  
    super.onStop();
}

public void onEvent(UpdateCountEvent event) {//get update message
    Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}

3.发布活动

在需要更新参数 的其他Activity或其他中编写以下代码Fragment

//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));
于 2015-02-13T09:38:40.637 回答
1

我一直在尝试很多不同的方法,但没有一个能真正解决我的问题。以下是我如何使用你们提供的各种解决方案来解决它。感谢大家。

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

我只想在 onResume() 之后刷新第 0 页。

 adapter=new PagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

@Override
protected void onResume() {
    super.onResume();

    if (adapter!=null) {
        adapter.flag_refresh=true;
        adapter.notifyDataSetChanged();
    }
}

在我的 FragmentsMain 中,有一个公共整数“页面”,它可以告诉我是否是我要刷新的页面。

public class FragmentsMain extends Fragment {

private Cursor cursor;
private static Context context;
public int page=-1;
于 2015-06-17T01:38:18.447 回答
1

这是我的实现,它结合了来自@Bill Phillips One 的信息,大多数情况下都会获取片段缓存,除非数据发生了变化。很简单,而且似乎工作正常。

MyFragmentStatePagerAdapter.java

private boolean mIsUpdating = false;
public void setIsUpdating(boolean mIsUpdating) {
        this.mIsUpdating = mIsUpdating;
    }


@Override
public int getItemPosition(@NonNull Object object) {

    if (mIsUpdating) {
        return POSITION_NONE;
    }
    else {
        return super.getItemPosition(object);
    }
}

我的活动.java

mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);
于 2019-01-09T17:08:24.370 回答
1

这可能对某人有所帮助 - 在我的情况下,当插入新页面时,视图寻呼机两次询问现有片段的位置,但不询问新项目的位置,导致不正确的行为和数据不显示。

  1. 复制 FragmentStatePagerAdapter 的源代码(似乎很久没有更新了)。

  2. 覆盖 notifyDataSetChanged()

    @Override
    public void notifyDataSetChanged() {
        mFragments.clear();
        super.notifyDataSetChanged();
    }
    
  3. 向 destroyItem() 添加健全性检查以防止崩溃:

    if (position < mFragments.size()) {
        mFragments.set(position, null);
    }
    
于 2016-08-23T13:34:38.600 回答
1

我知道派对迟到了。我已经通过调用解决了这个TabLayout#setupWithViewPager(myViewPager);问题FragmentPagerAdapter#notifyDataSetChanged();

于 2015-11-12T03:35:41.170 回答
1

如果您想使用 FragmentStatePagerAdapter,请查看https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary% 20 星&groupby=&sort=&id=37990。FragmentStatePagerAdapter 存在可能会或可能不会给您的用例带来麻烦的问题。

此外,链接也很少有解决方案..很少有可能适合您的要求。

于 2015-08-22T21:47:22.927 回答
1

使用ViewPager2FragmentStateAdapter

支持动态更新数据ViewPager2

文档中有一条关于如何使其工作的重要说明:

注意:DiffUtil 实用程序类依赖于通过 ID 识别项目。如果您使用 ViewPager2 对可变集合进行分页,则还必须覆盖 getItemId() 和 containsItem()。(强调我的)

根据ViewPager2 文档和 Android 的 Github示例项目,我们需要采取一些步骤:

  1. 设置FragmentStateAdapter和覆盖以下方法:、、、和getItemCount(注意:不支持)createFragmentgetItemIdcontainsItemFragmentStatePagerAdapterViewPager2

  2. 将适配器连接到ViewPager2

  3. 调度列表更新到ViewPager2with DiffUtil(不需要使用DiffUtil,如示例项目中所示)


例子:

private val items: List<Int>
    get() = viewModel.items
private val viewPager: ViewPager2 = binding.viewPager

private val adapter = object : FragmentStateAdapter(this@Fragment) {
    override fun getItemCount() = items.size
    override fun createFragment(position: Int): Fragment = MyFragment()
    override fun getItemId(position: Int): Long = items[position].id
    override fun containsItem(itemId: Long): Boolean = items.any { it.id == itemId }
}
viewPager.adapter = adapter
    
private fun onDataChanged() {
    DiffUtil
        .calculateDiff(object : DiffUtil.Callback() {
            override fun getOldListSize(): Int = viewPager.adapter.itemCount
            override fun getNewListSize(): Int = viewModel.items.size
            override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
                viewPager.adapter?.getItemId(oldItemPosition) == viewModel.items[newItemPosition].id

            override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
                areItemsTheSame(oldItemPosition, newItemPosition)
        }, false)
        .dispatchUpdatesTo(viewPager.adapter!!)
}
于 2021-02-02T19:09:30.710 回答
0

此解决方案不适用于所有人,但就我而言,我的 ViewPager 中的每个 Fragment 都是不同的类,并且一次只存在一个。

有了这个约束,这个解决方案是安全的,应该可以安全地在生产中使用。

private void updateFragment(Item item) {

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for (Fragment fragment : fragments) {

        if (fragment instanceof MyItemFragment && fragment.isVisible()) {
            ((MyItemFragment) fragment).update(item);
        }

    }
}

如果您有同一个片段的多个版本,您可以使用相同的策略来调用这些片段上的方法,以确定它是否是您要更新的片段。

于 2016-07-06T15:31:08.180 回答
0

如果要基于索引重新创建或重新加载片段,请使用 FragmentStatePagerAdapter 而不是 FragmentPagerAdapter 例如,如果要重新加载 FirstFragment 以外的片段,则可以像这样检查实例并返回位置

 public int getItemPosition(Object item) {
    if(item instanceof FirstFragment){
       return 0;
    }
    return POSITION_NONE;
 }
于 2018-06-11T14:09:09.617 回答
0

我已经浏览了上面的所有答案和其他一些帖子,但仍然找不到适合我的东西(具有不同的片段类型以及动态添加和删除选项卡)。FWIW 以下方法对我有用(以防其他人有同样的问题)。

public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
    private static final String TAB1_TITLE = "Tab 1";
    private static final String TAB2_TITLE = "Tab 2";
    private static final String TAB3_TITLE = "Tab 3";

    private ArrayList<String> titles = new ArrayList<>();
    private Map<Fragment, Integer> fragmentPositions = new HashMap<>();


    public MyFragmentStatePageAdapter(FragmentManager fm) {
        super(fm);
    }


    public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
        titles.clear();

        if (showTab1) {
            titles.add(TAB1_TITLE);
        }
        if (showTab2) {
            titles.add(TAB2_TITLE);
        }
        if (showTab3) {
            titles.add(TAB3_TITLE);
        }
        notifyDataSetChanged();
    }


    @Override
    public int getCount() {
        return titles.size();
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;

        String tabName = titles.get(position);
        if (tabName.equals(TAB1_TITLE)) { 
            fragment =  Tab1Fragment.newInstance();
        } else if (tabName.equals(TAB2_TITLE)) {
            fragment =  Tab2Fragment.newInstance();
        } else if (tabName.equals(TAB3_TITLE)) {
            fragment =  Tab3Fragmen.newInstance();
        } 

        ((BaseFragment)fragment).setTitle(tabName);
        fragmentPositions.put(fragment, position);
        return fragment;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }

    @Override
    public int getItemPosition(Object item) {
        BaseFragment fragment = (BaseFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        Integer fragmentPosition = fragmentPositions.get(item);
        if (fragmentPosition != null && position == fragmentPosition) {
            return POSITION_UNCHANGED;
        } else {
            return POSITION_NONE;
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragmentPositions.remove(object);
    }
}
于 2017-02-05T20:17:21.903 回答
0

您需要更改 instantiateItem 的 mFragments 元素 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);
            }
        }
    }

基于 AndroidX FragmentStatePagerAdapter.java,因为mFragments调用 notifyDataSetChanged() 时元素位置不会改变。

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

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

您可以运行此项目以确认如何工作。 https://github.com/cuichanghao/infivt

于 2020-04-09T14:19:23.163 回答