在选项卡内切换片段 [英] Switching fragments within tab

查看:17
本文介绍了在选项卡内切换片段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个使用 ActionBarSherlock 的应用.该应用程序由三个选项卡组成,在每个选项卡中,多个屏幕根据用户输入连续显示.我可以在选项卡之间切换片段,但是在 选项卡中切换片段会出现问题.我试过这样:

I'm creating an app that uses ActionBarSherlock. The app consists of three tabs, and in each of them, multiple screens are shown consecutively based on user input. I am able to switch Fragments between tabs, but the switching of fragments within tabs gives a problem. I've tried it like this:

在主类中:

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

确实替换了第二个片段的第一个片段,但是当我更改选项卡时,第二个片段仍然可见,在旧选项卡的内容之上显示新选项卡的内容.我想我需要以某种方式分离 onTabUnselected 中的第二个片段,但我不知道如何获取对这个片段的引用.

This does replace the first fragment for the second, but when I change tabs, the second fragment is still visible, showing the content of the new tab on top of the content of the old tab. I think somehow I need to detach the second fragment in onTabUnselected, but I have no idea how to get a reference to this Fragment.

谁能帮我解决这个问题?

Can anyone help me with this?

为了清楚起见,一些重要的类:

For clarity, some significant classes:

我的主要课程:

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 开发者网站上的 "Adding Navigations Tabs" 有一些小的改动):

The TabListener (from "Adding Navigations Tabs" on the Android developer site with some minor changes):

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

StationsFragment(RouteFragmentDelaysFragment是一样的,只是文字不同)

And StationsFragment (RouteFragment and DelaysFragment are the same, with only different text)

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

推荐答案

所以发生的事情是,在 TabListener 中,在 onTabUnselected 方法中,Fragment 没有分离,导致它在显示新的 Fragment 时仍然显示.

So what happened was that, in TabListener, in the onTabUnselected method, the Fragment was not detached, causing it to still be show while a new Fragment was shown.

造成这种情况的原因是,被分离的 Fragment 是第一个片段,而不是我的第二个片段.我做了一些改变.

The cause to this was, that the Fragment that was detached was the first fragment, and not my second fragment. I've made some changes.

Activity中:

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

这里我在 replace() 方法中添加了 "STATIONS" 标签,与第一个片段的标签相同.
TabListener 现在如下:

Here I've added the "STATIONS" tag in the replace() method, which is the same tag as the first fragment.
The TabListener is now as follows:

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,然后将其分离.

In the onTabUnselected method I now first retrieve the correct Fragment, then detach it.

希望这对某人有所帮助!

Hope this helps someone!

这篇关于在选项卡内切换片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆