如何将Fragment添加到FragmentPagerAdapter中的第一个位置

时间:2014-12-09 14:19:58

标签: android android-fragments android-viewpager android-fragmentactivity

我正在使用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>

4 个答案:

答案 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缓存中的现有活动片段。