web-dev-qa-db-ja.com

ViewPager内でフラグメントを別のフラグメントに置き換える

ViewPagerをFragmentPagerAdapterと一緒に使用して、3つの異なるフラグメントをホストしています

[Fragment1][Fragment2][Fragment3]

私が達成しようとしているのは、特定のタスクが成功した場合に、Fragment1をまったく新しいフラグメントFragment4で正常に置き換えることです。

私が使うとき.

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

..フラグメントは美しく置き換えられ、Fragment1の代わりにFragment4が表示されます。 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;
}

このコードでは何も行われませんが、誰かが私が間違っていることを見て、正しい方向に向けたい場合は、とても感謝しています!

23
velu

FragmentStatePagerAdapterを使用してみてください

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

cozは、ビューをスワイプすると(getitemを呼び出すときも)、フラグメントを削除するため、自分で明示的に削除する必要はありません。

私はそれが私のために働く同じ問題を抱えてきました。

私はあなたのコードを試してif (fragment!=null)ブロックを削除し、それが機能します。

11
Ridwan Yusuf

Maurycyが言ったように、フラグメントが置き換えられたことをViewPagerに伝えたいときはいつでもmAdapter.notifyDataSetChanged()を呼び出す必要があります。ただし、アダプターのgetItemPosition()抽象関数をオーバーライドし、古い非表示のフラグメントを引数として呼び出されると、POSITION_NONEを返す必要もあります。それ以外の場合、ViewPagerは現在のフラグメントをすべて保持します。

詳細とコード例については、「 this answer to a 関連する質問 」を参照してください。

3
wize

ちょっと私はこの問題をFragmentPagerAdapter内のリストを使用してさまざまなフラグメントを処理することで解決しました、そして私の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()
0
Maurycy

フラグメントのリロードを回避するために、offScreenPageLimitを5(またはユースケースに基づいて)に設定して、スワイプしたときにリロードされるのではなく、置き換えられたものが残るようにします。

    mViewPager.setOffscreenPageLimit(5);
0
Shangeeth Sivan

状況によっては、getItemステートメントがcase 0のfragment4を返さないようにしてください。

0
Sashi Kolli