使用 FragmentStatePagerAdapter 在 ViewPager 的两侧动态添加片段

Posted

技术标签:

【中文标题】使用 FragmentStatePagerAdapter 在 ViewPager 的两侧动态添加片段【英文标题】:Adding Fragments Dynamically on both side of the ViewPager using FragmentStatePagerAdapter 【发布时间】:2014-12-25 07:28:36 【问题描述】:

在我的一个应用程序中,我需要在 ViewPager 的两侧添加 Fragments。首先,我将获得 5 个提要的常量,我的 ViewPager 将在索引 2 处显示提要,即我当前显示的片段将包含索引 2 处的数据。所以总的来说,我的 ViewPager 将在开始时显示 5 个提要的中心,并且我只需像这样将 ViewPager 当前项设置为 2 即可实现

viewPager.setCurrentItem(2);

现在用户可以左右滑动,当他从中心位置向左滑动时,我将寻找下一个提要,即从服务器获取并像这样在我的 ViewPager 的零索引处添加提要

feedsList.add(0, modelClassObject); // feedsList will contain all feeds and has been used by adapter to show data in fragments.
adapter.notifyDataSetChanged();

当我从中心位置向右滑动时,我会像这样在最后添加提要

feedsList.add(modelClassObject);
adapter.notifyDataSetChanged();

现在的问题是,如果我只在右侧添加提要,即在提要列表的末尾,一切正常,但是当我在零索引处添加提要时,问题就来了。我的适配器没有显示已添加到零位置的新提要,而是重复现有提要之一,并且在右侧但不在左侧重复。我已经尝试了一切,但没有什么是正确的。这是我的适配器代码。

private class HorizontalPagerAdapter extends FragmentStatePagerAdapter 

    public HorizontalPagerAdapter(FragmentManager fm) 
        super(fm);
    

    @Override
    public Fragment getItem(int arg0) 
        return FeedUserProfileFragment.newInstance(feedsList.get(arg0),
                arg0);
    

    @Override
    public int getCount() 
        return feedsList.size();
    


这个我也用过

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

但没有结果.. :(

所以非常需要,如果有人早先这样做并面临同样的问题,请让我知道我做错了什么。我只需要在 ViewPager 的零索引处添加片段。

【问题讨论】:

贴出FeedUserProfileFragment.newInstance(feedsList.get(arg0),arg0);的代码 我认为这与这个问题没有任何关系 我也面临同样的问题。 【参考方案1】:

我之前也遇到过类似的问题,我的解决方法是:

    首先列表是在适配器本身中声明的,因此在创建该适配器的实例时我可以拥有它自己的列表。 修改了适配器类中的 getItem(int arg0) 方法,使其根据项目位置从列表中返回特定项目。 创建新片段时,使用实例化方法创建它,然后将其添加到您的片段中。

所以,完整的解决方案是:

适配器类:

private class HorizontalPagerAdapter extends FragmentStatePagerAdapter 

public List<Fragment> feedsList;

    public HorizontalPagerAdapter(FragmentManager fm) 
        super(fm);
    

    @Override
    public Fragment getItem(int position) 
        return feedsList.get(position);
    

    @Override
    public int getCount() 
        return feedsList.size();
    


以及在创建适配器时:

public static YourPageAdapter adapter_obj; // make sure it's static object
adapter_obj =  new YourPageAdapter(getSupportFragmentManager());
adapter_obj.feedsList = new ArrayList<Fragment>();
// then add the list of fixed fragments to it(the 5 in the beginning)
adapter_obj.feedsList = fragments_list; // an ArrayList contains the 5 fragments

以及何时要创建新片段:

adapter_obj.feedsList.add(0, Fragment.instantiate(mContext, ViewPager_Container_Class.class.getName(), page));
adapter_obj.notifyDataSetChanged();

【讨论】:

实际上我只使用一个片段,并且每次在同一个片段中的数据都会改变。所以你仍然认为我必须使用 Fragment ArrayList 或者我应该有一个 ArrayList 数据并在每次添加新提要时通知该 arrayList ?? 我认为您不必只是将数据添加到 ArrayList 并通知更改,我相信分段不会那么顺利,采用片段 ArrayList 或任何其他让您重新创建的方式从头开始的片段,以确保您的所有更改都将得到应用。 我不知道,但如果这是问题所在,那么我将无法在最后添加提要。所以它也应该这样工作。无论如何,我也试过你的,但导致我例外。我已经搜索了例外,但一切都是徒劳的。所以最后我决定暂时每次都设置适配器。 hmmm.. 让我们看看.. 等待正确的答案。反正谢谢。你的帮助真的很可观.. :) @MuhammedRefaat ***.com/questions/40149039/… 需要帮助【参考方案2】:

FragmentStatePagerAdapter 在前面添加新的 Fragment 时无法正确处理。

解决方法是这样的:

    在末尾添加一个新片段。 调用 notifyDataSetChanged(); 将片段放在前面。 调用 notifyDataSetChanged();

顺便说一句,getItemPosition() 应该一直返回正确的位置:

public int getItemPosition(Object object)

    return feedsList.indexOf( object );

所以,你的代码应该是:

newFrag = Fragment.instantiate(...);
feedsList.add( newFrag );
adapter_obj.notifyDataSetChanged();

feedsList.remove( feedsList.size() - 1 );
feedsList.add( 0, newFrag );
adapter_obj.notifyDataSetChanged();

我猜 FragmentStatePagerAdapter 的实现并不期望添加新片段和更改位置同时发生。

【讨论】:

你能解释一下为什么 FragmentPagerAdpter 不能处理添加到前面的对象吗?

以上是关于使用 FragmentStatePagerAdapter 在 ViewPager 的两侧动态添加片段的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)