我正在使用FragmentPagerAdapter和一个ViewPager来添加自定义片段 EDIT:来自我的MainActivity(还通过包发送基于JSON响应的一堆额外数据)并使用滑动动作移动到列表中的下一个片段。
public class MyPagerAdapter extends FragmentPagerAdapter implements Serializable {
public List<Fragment> fragments;
public FragmentManager fm;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
this.fm = fm;
this.fragments = new ArrayList<Fragment>();
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
}
只要我添加新的碎片,一切都正常 使用
MyPagerAdapter pageAdapter = new MyPagerAdapter(getSupportFragmentManager());
pager = (ViewPager)findViewById(R.id.myViewPager);
pageAdapter.fragments.add(new CustomFragment());
pager.setAdapter(pageAdapter);
但我找不到将片段添加到列表开头并向后滑动的正确方法。
我试过了两次
pageAdapter.fragments.add(0, new CustomFragment());
以及将FragmentPagerAdapters列表更改为LinkedList并使用
pageAdapter.fragments.addFirst(new CustomFragment());
然后使用
刷新适配器pageAdapter.notifyDataSetChanged();
我一直得到以下例外:
java.lang.IllegalStateException:无法更改片段的标签CustomFragment {2ead9520#10 id = 0x7f0a0002 android:switcher:2131361794:10}:was android:switcher:2131361794:10 now android:switcher:2131361794:11 < / p>
答案 0 :(得分:0)
您不应该以这种方式创建和添加片段。而只是在getItem中实例化片段,适配器将负责使用它们。这样做:
@Override
public Fragment getItem(int position) {
Fragment fragment = new CustomFragment();
fragments.add(fragment)
return fragment
}
答案 1 :(得分:0)
我建议你不要保留一个对片段的引用列表,因为它没有必要,你冒着创建内存泄漏的风险。 我要做的是仅在需要时才创建片段:
@Override
public Fragment getItem(int position) {
Fragment fragment = new MyFragment();
return fragment;
}
要解决您的问题,您应该根据需要创建片段,例如,如果您有不同类实例的片段,例如MyFragment的一个实例,另一个是YourFragment的实例,依此类推,请保留一个列表,说明哪种类型片段占据该位置。 例如:
myListMap = new HashMap<Integer, Integer>();
myListMap.put(position, type);
然后动态创建片段:
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
int type = ...find fragment type in that position ....
if(type == MYFRAGMENTTYPE) {
fragment = new MyFragment();
}
return fragment;
}
答案 2 :(得分:0)
不知道你是否仍然需要答案,但我试图做类似的事情并找到解决办法:)
由于您的=ArrayFormula(AVERAGE(if(text(B4:B,"dddd")="Monday",F4:G)))
功能,您收到了该例外。您将在函数接收的位置返回片段,并且此位置始终是数组的最后位置,因为这将对应于“典型”用法中最后添加的片段。
在您的情况下,您希望在第一个位置添加一个新片段,因此您的getItem
将返回相同片段的两倍并抛出异常。
要避免这种情况,您需要在Adapter中创建一个公共函数,并添加要添加的片段的索引,然后返回此特定片段。
PS:我现在在Kotlin开发仅约6个月了,所以它可能会有一些拼写错误。getItem
要从您的活动中调用此内容,请更改您的public int newFragmentIndex = 0;
public List<Fragment> fragments;
...
public void addFragmentAt(int index, Fragment fragment) {
newFragmentIndex = index;
pageAdapter.fragments.add(index, fragment);
notifyDataSetChanged();
}
public void addFragment(Fragment fragment) {
newFragmentIndex = fragments.size();
pageAdapter.fragments.add(fragment);
notifyDataSetChanged();
}
...
@Override
public Fragment getItem(int position) {
return fragments.get(newFragmentIndex);
}
到
pageAdapter.fragments.add(new CustomFragment());
并且
pageAdapter.fragments.addFragment(new CustomFragment());
到
pageAdapter.fragments.add(0, new CustomFragment());
希望这可以帮助您解决问题!
答案 3 :(得分:0)
目前还没有人谈过的关键方法是public int getItemPosition(Object)
,它用于在移动后将片段重新映射到页面,并且public long getItemId(int position)
必须被寻呼机适配器覆盖重新排序片段。默认实现使用页面的位置作为id,因此重新排序会混淆FragmentPagerAdapter
。
(我遗漏了Serializable接口,因为它与回答问题无关 - 如何重新排序FragmentPagerAdapter中的片段。)
public class MyPagerAdapter extends FragmentPagerAdapter {
public List<Fragment> fragments;
public FragmentManager fm;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
this.fm = fm;
this.fragments = new ArrayList<Fragment>();
}
void addFragmentAtPosition(int position, Fragment f) {
if(position == fragments.size())
fragments.add(f);
else
fragments.add(position, f);
notifyDataSetChanged();
}
void removeFragmentAtPosition(int position) {
Fragment f = fragments.remove(position);
if(f != null)
fm.beginTransaction().remove(f).commit();
notifyDataSetChanged();
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
@Override
public int getItemPosition(Object object){
/*
* called when the fragments are reordered to get the
* changes.
*/
int idx = fragments.indexOf(object);
return idx < 0 ? POSITION_NONE : idx;
}
@Override
public long getItemId(int position) {
/*
* map to a position independent ID, because this
* adapter reorders fragments
*/
return System.identityHashCode(fragments.get(position));
}
}
关键的补充是public int getItemPosition(Object)
和public long getItemId(int)
的覆盖。这些允许FragmentPagerAdapter
重新定位现有片段并正确识别FragmentManager
缓存中的现有活动片段。