gpt4 book ai didi

java - 接下来在已经运行的Android ViewPager中插入新的Fragment

转载 作者:行者123 更新时间:2023-11-30 08:52:09 24 4
gpt4 key购买 nike

尝试将片段动态添加到Android ViewPager中的不同页面。

动态地将片段添加到片段列表的末尾可以很好地工作,但是尝试将其添加到下一个插槽(当前可见页面之后的看不见的页面)。我尝试将其添加到片段的数组列表中,并使用notifyDataSetChanged,并尝试在将每个片段设置为上一个项目之后在每个片段上使用set。

编辑:更新的代码

class MainPagerAdapter extends FragmentPagerAdapter {

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

@Override
public PageFragment getItem(int position) {
return PageFragment.newInstance(Datamart.getInstance().getURLs().get(position));
}

@Override
public int getCount() {
return Datamart.getInstance().getURLs().size();
}

@Override
public int getItemPosition(Object object) {
PageFragment pageFragment = (PageFragment) object;
for ( int i = 0; i < getCount(); i++ ) {
if ( pageFragment.getURL().equals( Datamart.getInstance().getURLs().get(i) ) ) {
return i;
}
}
return POSITION_NONE;
}
}


在Datamart中:

public class Datamart {

static Datamart instance;

private ArrayList<String> URLs;
private MainPagerAdapter mainPagerAdapter;
private ViewPager viewPager;

public Datamart() {
URLs = new ArrayList<>();
}

public static Datamart getInstance() {
if (instance == null) {
instance = new Datamart();
}
return instance;
}

public MainPagerAdapter getMainPagerAdapter() {
return mainPagerAdapter;
}

public void setMainPagerAdapter(MainPagerAdapter mainPagerAdapter) {
this.mainPagerAdapter = mainPagerAdapter;
}

public ViewPager getViewPager() {
return viewPager;
}

public void setViewPager(ViewPager viewPager) {
this.viewPager = viewPager;
}

public void addToEnd( String URL ) {
URLs.add(URL);
mainPagerAdapter.notifyDataSetChanged();
}

public void addNext( String URL ) {
URLs.add(viewPager.getCurrentItem() + 1, URL);
mainPagerAdapter.notifyDataSetChanged();
}

public ArrayList<String> getURLs() {
return URLs;
}

public void setURLs(ArrayList<String> URLs) {
this.URLs = URLs;
}
}

最佳答案

ViewPager尽最大努力尝试跟踪所有片段的去向,但由于将片段插入中间而没有告知,您感到困惑。

让我们做一个例子。假设您有两页,那么您将显示第一页,第二页是右侧的屏幕外页。您第一页有fragment0,第二页有fragment1

首先,请记住,由于ViewPager正在左右管理屏幕外页面,因此它已经认为知道第二个页面片段是什么,即fragment1

在现有页面片段之间插入片段时,ViewPager不会立即询问您第二个位置的片段,而是要询问第二个位置的片段是否已更改。

这是getItemPosition()的来源。您没有在getItemPosition()中实现FragmentPagerAdapter,所以getItemPosition()的默认行为是返回POSITION_UNCHANGED。 (如您所见,这就是为什么在末尾添加片段不会导致错误的原因。)

因此,当您调用notifyDataSetChanged()时,ViewPager调用了getCount()并看到有两个页面,而不是两个页面。然后,它为第0页和第1页(它知道的页面)调用getItemPosition(),并且您的默认实现告诉它什么都没有改变。

但是确实发生了变化,您在两个现有页面的中间插入了一个页面/片段。 ViewPager询问您第二页是否更改,并且您的getItemPosition()应该返回了2而不是POSITION_UNCHANGED

现在,由于您的getCount()返回了3而不是2,因此ViewPager知道末尾有一个新页面,它不知道,因此它调用getItem()来获取新片段。

这是发生错误的地方。您的getItem()方法在第3页返回了fragment1,并且ViewPager阻塞了,因为您将它已经知道的片段交给了它。具体来说,它将片段的标签用于一些内部管理。它在页面的容器ID和项目位置(页面编号)之外创建标签。因此,在任何给定时间,它都期望(a)标签为空,或者(b)标签将与根据容器ID和商品位置已经计算出的值相同。这些条件都不是正确的,所以这就是抛出IllegalStateException的原因。

那么如何解决这个问题?

您实现一个做正确的事情的getItemPosition()。调用getItemPosition()时,将扫描片段列表,找到匹配的片段时,将返回片段的索引。如果删除了一个片段,使得列表中没有匹配的片段,则返回POSITION_NONE告诉ViewPager应该删除该页面。 ViewPager然后将调用您的getItem()方法以获取新页面。这样,ViewPager可以始终与适配器保持同步。



编写FragmentPagerAdapter时,我什至不使用模型中的片段。如果我正在编写您的适配器,那么我将只有一个URL列表,因为看起来每个页面/片段都有其自己的唯一URL。

我还将在fragment类上实现一个getUrl()方法,以获取用于创建该fragment的URL。

因此,对于getItemPosition(),我将在传入的片段上调用getUrl(),然后在适配器的列表中搜索该URL。然后,我将返回列表中URL的索引,如果不存在,则返回POSITION_NONE

然后在getItem()中,我将使用传入的列表位置处的URL实例化一个新片段。我的规则是,直到ViewPager通过调用getItem()专门请求它之前,我才不会实例化一个片段。

这样,只有ViewPager会访问这些片段,而我不会遇到这些类型的问题。

另外,在ViewPager调用startUpdate()到调用finishUpdate()的时间之间,请勿对适配器模型进行任何更改。这就是ViewPager告诉适配器它在确定所有页面片段的去向的“关键部分”中的方式。

PagerAdapter可以忍受。在getCount()getItemPosition()getItem()方法中放入一些调试日志,以便您了解ViewPager如何使用适配器管理其页面。

关于java - 接下来在已经运行的Android ViewPager中插入新的Fragment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30282516/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com