将片段替换为ViewPager中的另一个片段

时间:2011-09-16 13:30:17

标签: android android-fragments android-viewpager

我正在使用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就在那里。所以这个解决方案的问题在于,即使我尝试删除Fragment1,我也找不到立即显示Fragment4的方法:

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;
}

有了这段代码,我什么都没做,但如果有人看到我做错了什么,并想指出我正确的方向,我会非常感激!

6 个答案:

答案 0 :(得分:10)

尝试使用FragmentStatePagerAdapter

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

因为你在浏览视图时也会删除片段(当你调用getitem时也是如此),所以你不需要自己明确删除它们。

我遇到了同样适合我的问题。

我尝试使用您的代码并移除if (fragment!=null)块,但它可以正常工作。

答案 1 :(得分:3)

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

嘿我通过在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()

答案 4 :(得分:0)

有关如何使用ViewPagerFragmentPagerAdapter插入/替换标签,请参阅我的answer类似问题。

答案 5 :(得分:0)

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

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" id="studio" viewBox="0 0 1127.55 928.38"><defs><style>.cls-1{fill:none;stroke:#867874;stroke-miterlimit:20;stroke-width:2px}.cls-2{fill:#867874;}</style></defs><title>mobilestudio</title><g id="Livello_2" data-name="Livello 2"><g id="Livello_1-2" data-name="Livello 1"><rect class="cls-1" x="323.51" y="642.71" width="430.77" height="194.75" rx="10.97" ry="10.97"/><path class="cls-1" d="M712.87,606H364.92a12.57,12.57,0,0,1-12.57-12.57V463a12.57,12.57,0,0,1,12.57-12.57H727"/><rect class="cls-1" x="408.92" y="605.98" width="25.38" height="36.72"/><rect class="cls-1" x="643.49" y="605.98" width="25.38" height="36.72"/><rect class="cls-1" x="706.64" y="605.98" width="25.38" height="36.72"/><path class="cls-1" d="M354.39,837.46c-8,0-16,6.31-16,37.46v53h17.8V875.37c0-8.46,2.22-37.91,22.25-37.91"/><path class="cls-1" d="M723.4,837.46c8,0,16,6.31,16,37.46v53h-17.8V875.37c0-8.46-2.22-37.91-22.25-37.91"/><path class="cls-1" d="M728.21,450.43H743a11,11,0,0,1,11,11V595a11,11,0,0,1-11,11H695.81a11,11,0,0,1-11-11V493.88a43.45,43.45,0,0,1,43.45-43.45Z"/><line class="cls-1" y1="927.88" x2="1127.55" y2="927.88"/><path class="cls-1" d="M970,186.46a83.92,83.92,0,0,0,48.43-76.06H850.65a83.9,83.9,0,0,0,47.91,75.81"/><path class="cls-1" d="M935.38,221.32h5.47c2.17-16,14-24.44,31.72-36.1H935.38"/><path class="cls-1" d="M934.55,221.32h-5.47c-2.17-16-14-24.44-31.71-36.1h37.18"/><path class="cls-1" d="M934.55,77.44a33,33,0,0,0-33,33h65.94A33,33,0,0,0,934.55,77.44Z"/><rect class="cls-1" x="929.16" y="221.32" width="11.69" height="694.19"/><rect class="cls-1" x="865.22" y="915.51" width="139.34" height="11.61"/><rect class="cls-1" x="134.72" y="12.72" width="328.47" height="220.32" rx="10.97" ry="10.97"/><rect class="cls-1" x="145.64" y="23.36" width="306.62" height="199.04" rx="6.7" ry="6.7"/><polygon class="cls-1" points="198.24 12.72 205.01 1 211.78 12.72 198.24 12.72"/><polygon class="cls-1" points="386.12 12.72 392.89 1 399.66 12.72 386.12 12.72"/><rect class="cls-1" x="198.53" y="98.55" width="45.89" height="43.45"/><circle class="cls-2" cx="221.47" cy="98.55" r="4.07"/><rect class="cls-1" x="278" y="70.69" width="45.89" height="43.45"/><circle class="cls-2" cx="300.95" cy="70.69" r="4.07"/><rect class="cls-1" x="352.36" y="142.75" width="45.89" height="43.45"/><circle class="cls-2" cx="375.3" cy="142.75" r="4.07"/><path class="cls-1" d="M940.85,221.32c0,17,9.82,211.49,21.16,298.88,7.67,59.12,51.68,376.46,111.26,407.68"/><rect class="cls-2" x="958.39" y="516.85" width="9.5" height="24.52" rx="2.17" ry="2.17" transform="translate(-60.35 129.03) rotate(-7.43)"/><line class="cls-1" x1="934.5" y1="62.35" x2="934.5" y2="40.6"/><line class="cls-1" x1="910.49" y1="68.83" x2="902.57" y2="55.12"/><line class="cls-1" x1="892.93" y1="86.45" x2="874.1" y2="75.58"/><line class="cls-1" x1="976.17" y1="86.3" x2="995" y2="75.42"/><line class="cls-1" x1="958.54" y1="68.74" x2="966.41" y2="55.12"/></g></g></svg>