【问题标题】:Replace fragment with another fragment inside ViewPager用 ViewPager 中的另一个片段替换片段
【发布时间】:2011-11-18 17:08:57
【问题描述】:

我使用 ViewPager 和 FragmentPagerAdapter 来托管三个不同的片段

[Fragment1][Fragment2][Fragment3]

如果特定任务成功,我想要实现的是用一个全新的片段 Fragment4 成功替换 Fragment1。

当我使用..

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.fragment1_layout_id, fragment4);
transaction.commit();

..片段被漂亮地替换了,显示的是片段 4 而不是片段 1。虽然我一路刷到Fragment3再刷回Fragment4,Fragment1又卷土重来了。

再一次,如果我使用..

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.remove(fragment1);
transaction.commit();

..Fragment1 被删除,当我回来时 Fragment4 就在那里。所以这个解决方案的问题是我无法找到一种方法来立即显示 Fragment4 因为 Fragment1 被删除,即使我尝试过:

transaction.add(fragment4);
transaction.show(fragment4);

这是我的 FragmentPagerAdapter 实现目前的样子,没有任何事务管理

public static class PagerAdapter extends FragmentPagerAdapter {

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

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

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = null;

        switch (position) {
        case 0:
            fragment = Fragment1.newInstance(context_);
            break;

        case 1:
            fragment = Fragment2.newInstance(context_);
            break;

        case 2:
            fragment = Fragment3.newInstance(context_);
            break;

        default:
            break;
        }

        return fragment;
    }
}

编辑。

所以我的问题似乎并不完全清楚。我决定删除我之前设法创建的所有意大利面,并试图声明我已将它们删除(请参阅上面的粗体文本)。

无论如何,这几乎就是我在 getItem() 中尝试做的事情:

@Override
public Fragment getItem(int position) {

    Fragment fragment = null;

    switch (position) {
    case 0:

        if (!app.isUserLoggedIn) {
            if (loginFragment_ == null) {
                loginFragment_ = LoginFragment.newInstance(context_);
                transaction_ = fragmentManager_.beginTransaction();

                if (logoutFragment_ != null) {
                    transaction_.remove(logoutFragment_);
                    logoutFragment_ = null;
                }

                transaction_.add(loginFragment_, "login");
                transaction_.commit();
            }

            if (fragmentManager_.findFragmentByTag("login") == null)
                fragment = LoginFragment.newInstance(context_);
            else
                fragment = fragmentManager_.findFragmentByTag("login");

        } else {
            if (logoutFragment_ == null) {                      
                logoutFragment_ = LogoutFragment.newInstance(context_);
                transaction_ = fragmentManager_.beginTransaction();

                if (loginFragment_ != null) {
                    transaction_.remove(loginFragment_);
                    loginFragment_ = null;
                }

                transaction_.add(logoutFragment_, "logout");
                transaction_.commit();
            }

            if (fragmentManager_.findFragmentByTag("logout") == null)
                fragment = LogoutFragment.newInstance(context_);
            else
                fragment = fragmentManager_.findFragmentByTag("logout");
        }
        break;

    case 1:
        fragment = HomeFragment.newInstance(context_);
        break;

    case 2:
        fragment = RegisterFragment.newInstance(context_);
        break;

    default:
        break;
    }

    return fragment;
}

使用这段代码我什么都做不了,但如果有人看到我做错了什么并想指出我正确的方向,我将不胜感激!

【问题讨论】:

  • 我认为您应该更改 PagerAdapter 中的 getItem。返回的片段必须可见。
  • @dziobas 这正是我一直在尝试实现我在问题中描述的魔法的地方,但没有运气。
  • 请参阅我的answer 以了解有关如何使用ViewPagerFragmentPagerAdapter 插入/替换选项卡的类似问题。
  • fragment2 在我点击 tab1 时被调用,我不知道为什么 tab2 被调用?是适配器错误吗?

标签: android android-fragments android-viewpager


【解决方案1】:

尝试使用 FragmentStatePagerAdapter

http://android-developers.blogspot.com/2011_08_01_archive.html

因为它会在您滑动视图时移除片段(也当您调用 getitem 时),因此您不需要自己显式移除它们。

我也遇到了同样的问题。

我尝试您的代码并删除 if (fragment!=null) 块,它可以工作。

【讨论】:

  • 你能显示一些代码吗?我将不胜感激,因为我按照您的步骤进行操作,但没有得到我想要的...
【解决方案2】:

就像 Maurycy 所说,每当您想告诉 ViewPager 片段已被替换时,您都需要调用 mAdapter.notifyDataSetChanged()。但是,您还需要覆盖适配器中的 getItemPosition() 抽象函数,并在使用旧的、要隐藏的片段作为参数调用时返回 POSITION_NONE。否则,ViewPager 将保留所有当前片段。

有关更多信息和示例代码,请参阅this answerrelated question

【讨论】:

    【解决方案3】:

    在某些情况下,您的getItem 语句不应该为case 0 返回fragment4 吗?

    【讨论】:

    • 是的,它应该而且我整天都在尝试找出正确的方法来做到这一点。我更新了我的问题并添加了到目前为止我一直在尝试的方法。
    【解决方案4】:

    嘿,我已经解决了这个问题,方法是在我的 FragmentPagerAdapter 中使用 List 来处理各种片段,然后我的 getItem 就是这样......

        public void addScreen(String tag, Class<?> clss, Bundle args){
            if(clss!=null){
                TabInfo info = new TabInfo(tag, clss, args);
                screens.add(info);
            }
        }
    @Override
        public Fragment getItem(int position) {
            TabInfo info = screens.get(position);
            return Fragment.instantiate(context, info.clss.getName(), info.args);
        }
    

    然后我以编程方式删除/添加/重新排列列表项(片段),然后调用处理程序

    mAdapter.notifyDataSetChanged()
    

    【讨论】:

      【解决方案5】:

      尝试将 offScreenPageLimit 设置为 5(或根据您的用例)以避免重新加载片段,以便您替换的内容将保留而不是在您滑动时重新加载。

          mViewPager.setOffscreenPageLimit(5);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多