web-dev-qa-db-ja.com

タブ内のフラグメントの切り替え

ActionBarSherlockを使用するアプリを作成しています。アプリは3つのタブで構成されており、各タブにはユーザー入力に基づいて複数の画面が連続して表示されます。タブ間でフラグメントを切り替えることはできますが、フラグメントの切り替えwithinタブで問題が発生します。私はこのようにそれを試しました:

メインクラス:

SingleStationFragment singleStationFragment = new SingleStationFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(Android.R.id.content, singleStationFragment);
transaction.addToBackStack(null);
transaction.commit();

これdoes最初のフラグメントを2番目のフラグメントに置き換えますが、タブを変更すると、2番目のフラグメントが引き続き表示され、古いタブのコンテンツの上に新しいタブのコンテンツが表示されます。どういうわけかonTabUnselectedの2番目のフラグメントをデタッチする必要があると思いますが、このフラグメントへの参照を取得する方法がわかりません。

誰かがこれで私を助けることができますか?

明確にするために、いくつかの重要なクラス:

私のメインクラス:

public class TreinVerkeer extends SherlockFragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupTabs(savedInstanceState);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getSupportMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    private void setupTabs(Bundle savedInstanceState) {
        ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        Tab tab = actionBar.newTab().setText("STATIONS").setTabListener(new TabListener<StationsFragment>(this, "stations", StationsFragment.class));
        actionBar.addTab(tab);

        tab = actionBar.newTab().setText("ROUTE").setTabListener(new TabListener<RouteFragment>(this, "route", RouteFragment.class));
        actionBar.addTab(tab);

        tab = actionBar.newTab().setText("DELAYS").setTabListener(new TabListener<DelaysFragment>(this, "delays", DelaysFragment.class));
        actionBar.addTab(tab);

        if (savedInstanceState != null) {
            actionBar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
    }
}

TabListener( Android開発者サイト の「ナビゲーションタブの追加」から、いくつかのマイナーな変更があります):

public class TabListener<T extends SherlockFragment> implements com.actionbarsherlock.app.ActionBar.TabListener {
    private SherlockFragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    /**
     * Constructor used each time a new tab is created.
     * 
     * @param activity
     *            The Host Activity, used to instantiate the fragment
     * @param tag
     *            The identifier tag for the fragment
     * @param clz
     *            The fragment's Class, used to instantiate the fragment
     */
    public TabListener(Activity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    /* The following are each of the ActionBar.TabListener callbacks */

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
    SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag);

    // Check if the fragment is already initialized
    if (mFragment == null && preInitializedFragment == null) {
        // If not, instantiate and add it to the activity
        mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName());
        ft.add(Android.R.id.content, mFragment, mTag);
    } else if (mFragment != null) {
        // If it exists, simply attach it in order to show it
        ft.attach(mFragment);
    } else if (preInitializedFragment != null) {
        ft.attach(preInitializedFragment);
        mFragment = preInitializedFragment;
    }
}

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            // Detach the fragment, because another one is being attached
            ft.detach(mFragment);
        }
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}

そして、StationsFragmentRouteFragmentDelaysFragmentは同じですが、テキストが異なります)

public class StationsFragment extends SherlockFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.stationsfragment, container, false);
    }
}
20
nhaarman

つまり、TabListeneronTabUnselectedメソッドでは、Fragmentが切り離されておらず、新しいFragmentが表示されている間も表示されたままでした。示されていた。

これの原因は、切り離されたFragmentが最初のフラグメントであり、私の2番目のフラグメントではなかったためです。いくつか変更を加えました。

Activity

_SingleStationFragment singleStationFragment = new SingleStationFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(Android.R.id.content, singleStationFragment, "STATIONS");
transaction.addToBackStack(null);
transaction.commit();
_

ここでは、最初のフラグメントと同じタグである_"STATIONS"_タグをreplace()メソッドに追加しました。
TabListenerは次のようになりました。

_public class TabListener<T extends SherlockFragment> implements com.actionbarsherlock.app.ActionBar.TabListener {
    private final SherlockFragmentActivity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    private SherlockFragment mFragment;

    public TabListener(SherlockFragmentActivity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag);
        if (preInitializedFragment == null) {
            mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName());
            ft.add(R.id.treinverkeer_fragmentcontent, mFragment, mTag);
        } else {
            ft.attach(preInitializedFragment);
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag);

        if (preInitializedFragment != null) {
            ft.detach(preInitializedFragment);
        } else if (mFragment != null) {
            ft.detach(mFragment);
        }
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}
_

onTabUnselectedメソッドでは、最初に正しいFragmentを取得してから、それをデタッチします。

これが誰かを助けることを願っています!

24
nhaarman